Author | Topic: Uso di Word e BookMark (Segnalibri ) | |
---|---|---|
Solving | Uso di Word e BookMark (Segnalibri ) on Fri, 24 Oct 2014 18:24:42 +0200 Qualcuno fa' uso di word e BookMark ? Sto' usando l'esempio di alaska e il tutto funziona ma se uso lo stesso bookmark piu' volte nello stesso documento il cambio avviene solo sul primo. Ho letto in giro che cio' e' normale qualcuno ha sirsolto in modo diverso ? Grazie | |
Fabio Cavallone | Re: Uso di Word e BookMark (Segnalibri ) on Tue, 28 Oct 2014 10:21:39 +0100 Ciao, il bookmark è (e deve) essere un riferimento UNIVOCO all'interno del documento (non è un campo di mail-merge), per cui, se ti serve far comparire gli stessi valori in posti differenti, ti conviene utilizzare una tua notazione (tipo codArticolo_01, codArticolo_02, ecc...), anche se poi molto dipende da come gestisci i bookmark a livello di procedura Fabio "Solving" ha scritto nel messaggio news:722e2a25$65f2300e$31c3e@news.alaska-software.com... Qualcuno fa' uso di word e BookMark ? Sto' usando l'esempio di alaska e il tutto funziona ma se uso lo stesso bookmark piu' volte nello stesso documento il cambio avviene solo sul primo. Ho letto in giro che cio' e' normale qualcuno ha sirsolto in modo diverso ? Grazie | |
Solving | Re: Uso di Word e BookMark (Segnalibri ) on Tue, 28 Oct 2014 11:29:15 +0100 Ciao. ------------------------------------------------------------------------------- Ho Usato i file Word con estension .rtf e con il comando Memoread e Strtran ho risolto in parte il problema di usare piu' volte lo stesso riferimento solo che a volte ( anche i riferimenti singoli non duplicati) non vengono individuati e rimangono non "valorizzati". Con questo metodo il file Word contiene i campi nel seguente modo : #Cognome# e quindi eseguo un Strtran( cFile, "#Cognome#", cValore ) ------------------------------------------------------------------------------- Poi ho usato l'esempio di Alaska ************* ESEMPIO 1 con Riferimenti/Bookmark ********** In un vettore carico i dati necessari Esempio : {"Campo_Rif", "Valore da Sostituire"} {"Cognome", "Rossi"} Creo nel file Word il riferimento a Cognome e lo piazzo nella posizione voluta. Esecuzione della Funzione : cFile := WordFillDocument( cNome, nF, aData, xPdf ) ////////////////////////////////////////////////////////////////////// Open a MS Word document and replace the bookmarks with the values passed in the array aData. The resulting document is then saved back to the hard drive. ////////////////////////////////////////////////////////////////////// STATIC FUNCTION XWordFillDocument( cFile, nF, aData, xPdf ) LOCAL oWord, oBM, oDoc, i LOCAL cSave, cSavePdf, cDir, cRet := "" cDir := CurDrive() + ":\" + CurDir() cSave := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".DOC" cSavePdf := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".PDF" * --- Create a Word ActiveX component oWord := CreateObject("Word.Application") IF Empty( oWord ) dbMsgW( "Microsoft Word NON Installato Su Questo PC" ) ENDIF *oWord:visible := .T. *--- Open a Word document and retrieve the bookmarks * collection. oWord:documents:open( cFile ) oDoc := oWord:ActiveDocument oBM := oDoc:Bookmarks * --- Replace the Bookmark with a new value FOR i = 1 TO LEN( aData ) ReplaceBookmark(oBM , aData[i,1], aData[i,2] ) NEXT * --- Save the resulting Word document oDoc:saveas( cSave ) cRet := cSave * --- Crea File Pdf IF xPdf == "X" oDoc:ExportAsFixedFormat( cSavePdf, 17 ) cRet := cSavePdf ENDIF * --- Close the document and destroy the ActiveX * object oDoc:close() oWord:Quit() oWord:destroy() RETURN( cRet ) ////////////////////////////////////////////////////////////////////// Searches for a bookmark cBM by name in a given bookmark collection oBM, and assigns a new value cValue. ////////////////////////////////////////////////////////////////////// STATIC FUNCTION ReplaceBookmark( oBM, cBM, cValue ) LOCAL lRet := oBM:Exists(cBM), oF IF lRet oF := oBM:Item( cBM ) oF:Range:Text := cValue oF:Destroy() ENDIF RETURN(lRet) Naturalmente Il bookmark e' Univoco e lo posso duplicare piu' volte cambiando qualcosa tipo Nome1, Nome2, etc.. Questo se si sa' quante volte serve. La mia intenzione era dare un elenco dei campi_Rif che si possono usare all'utente finale e lui si costruisce il file in Word ed inserisce i riferimenti voluti, il problema e' alcuni campi_rif puo'/vuole usarli piu' volte, questo significa mettere mano alla procedura e duplicare i cam_rif interessati ogni volta che nasce l'esigenza dell'utente finale. Cioe' la prima volta gli basta usare il campo Cognome una volta , poi decide di usarlo una seconda volta nel testo (e creo Cognome2) , poi una terza (e creo Cognome3), poi .... Non mi va bene cosi'. ************* ESEMPIO 2 Via di Mezzo a Strtran ********** Esempio trovato su sito Tedesco Questo metodo sembra migliore ma ha una pecca e' un po' lento ( i primi due esempi sopra sono molto piu' veloci ) In un vettore carico i dati necessari Esempio : {"#Campo_Rif", "Valore da Sostituire"} {"#Cognome", "Rossi"} STATIC FUNCTION WordFillDocument( cFile, nF, aData, xPdf ) LOCAL oWord, oDoc, oWords, lSimbolo, i, nPos LOCAL cSave, cSavePdf, cDir, cRet := "", cX cDir := CurDrive() + ":\" + CurDir() cSave := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".DOC" cSavePdf := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".PDF" oWord := CreateObject("Word.Application") IF Empty( oWord ) dbMsgW( "Microsoft Word NON Installato Su Questo PC" ) RETURN NIL ENDIF oWord := oWord:dynamicCast(ActiveXObject()) oWord:Visible := .F. *oWord:Visible := .T. oWord:documents:open(cFile, .F., .T.) oDoc := oWord:ActiveDocument oWords := oDoc:Words lSimbolo := .F. FOR i := 1 to oWords:Count * --- Cosa Cercare -> # + Parola cX := "#" + ALLTRIM( oWords:Item(i):Text ) * --- Scansione per Ricerca Simbolo # nPos := ASCAN( aData, {|aVal| aVal[1] == cX } ) * --- Se Trovato if lSimbolo .AND. nPos > 0 *DBMSGW(aData[nPos,1] + " " + aData[nPos,2], oWords:Item(i):Text) * --- Sostituzione Variabile con Testo oWords:Item(i):Text := aData[nPos,2] + " " * --- Rimuove # dal Testo Rimpiazzato oWords:Item(i-1):Text := "" endif * --- Imposta Simbolo lSimbolo := oWords:Item(i):Text == "#" NEXT * --- Ritorno nome di file generato cRet := cSave oDoc:saveas( cSave ) * --- Crea File Pdf IF xPdf == "X" oDoc:ExportAsFixedFormat( cSavePdf, 17 ) cRet := cSavePdf ENDIF * oWord:Visible := .t. * oWord:Application:Activate() oDoc:close() oWord:Quit() oWord:Destroy() dbMsgW( "Conversione Completata" ) RETURN( cRet ) ************* Considerazioni : Con bookmark e' veloce, l'utente si puo' gestire il file (word) da creare e piazzare i campi_riferimenti (da una lista campi che genera il programma) ma se si usa il campo piu' volte devo intervenire nel sorgente per duplicare il campo e inserirlo nella lista. Con Strtran e' veloce, l'utente si puo' gestire il file (word) da creare e piazzare i #Campi# (da una lista campi che genera il programma) anche piu' volte con lo stesso nome ma ha volte non vengono sostituiti (?) per risolvere il problema devono aprire il file (word) e spostare o reimpostare il campo che non viene sostituito risalvare e funziona. Con Esempio 2 funziona tutto ma e' piu lento rispetto ai primi due metodi. Altre idee ben accette. | |
Fabio Cavallone | Re: Uso di Word e BookMark (Segnalibri ) on Tue, 28 Oct 2014 12:26:36 +0100 Ciao, poichè, a quanto ho capito, i bookmark utilizzabili sono definiti da te (tipo CodArt, CodCli, RagSoc, ...) potresti concordare (col cliente) una convenzione, del del tipo CodArt = CodArt01= CodArt02, ecc... Magari, modifichi il tuo array di riferimento in {<nome bookmark>, <lunghezza del nome>, <valore di riferimento>} aRifBookmarks := {<nome bookmark>, <lunghezza del nome>, <valore di riferimento>} oDoc:= oWord:ActiveDocument nBookmarks := oDoc:Bookmarks:Count FOR i := 1 TO nBookmarks nPos := aScan( aRifBookmarks, {|x| lower(x[1])==lower(left(oDoc:Bookmarks(i):Name, x[2]))}) IF nPos > 0 ReplaceBookmark( oDoc:Bookmarks(i), oDoc:Bookmarks(i):Name, aRifBookmarks[nPos,3] ) ENDIF NEXT P.S. Tieni presente che ho scritto tutto "al volo", ma, tolte possibili correzioni, la logica dovrebbe funzionare. Fabio "Solving" ha scritto nel messaggio news:59b17b7f$5c25c537$99ba@news.alaska-software.com... Ciao. ------------------------------------------------------------------------------- Ho Usato i file Word con estension .rtf e con il comando Memoread e Strtran ho risolto in parte il problema di usare piu' volte lo stesso riferimento solo che a volte ( anche i riferimenti singoli non duplicati) non vengono individuati e rimangono non "valorizzati". Con questo metodo il file Word contiene i campi nel seguente modo : #Cognome# e quindi eseguo un Strtran( cFile, "#Cognome#", cValore ) ------------------------------------------------------------------------------- Poi ho usato l'esempio di Alaska ************* ESEMPIO 1 con Riferimenti/Bookmark ********** In un vettore carico i dati necessari Esempio : {"Campo_Rif", "Valore da Sostituire"} {"Cognome", "Rossi"} Creo nel file Word il riferimento a Cognome e lo piazzo nella posizione voluta. Esecuzione della Funzione : cFile := WordFillDocument( cNome, nF, aData, xPdf ) ////////////////////////////////////////////////////////////////////// Open a MS Word document and replace the bookmarks with the values passed in the array aData. The resulting document is then saved back to the hard drive. ////////////////////////////////////////////////////////////////////// STATIC FUNCTION XWordFillDocument( cFile, nF, aData, xPdf ) LOCAL oWord, oBM, oDoc, i LOCAL cSave, cSavePdf, cDir, cRet := "" cDir := CurDrive() + ":\" + CurDir() cSave := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".DOC" cSavePdf := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".PDF" * --- Create a Word ActiveX component oWord := CreateObject("Word.Application") IF Empty( oWord ) dbMsgW( "Microsoft Word NON Installato Su Questo PC" ) ENDIF *oWord:visible := .T. *--- Open a Word document and retrieve the bookmarks * collection. oWord:documents:open( cFile ) oDoc := oWord:ActiveDocument oBM := oDoc:Bookmarks * --- Replace the Bookmark with a new value FOR i = 1 TO LEN( aData ) ReplaceBookmark(oBM , aData[i,1], aData[i,2] ) NEXT * --- Save the resulting Word document oDoc:saveas( cSave ) cRet := cSave * --- Crea File Pdf IF xPdf == "X" oDoc:ExportAsFixedFormat( cSavePdf, 17 ) cRet := cSavePdf ENDIF * --- Close the document and destroy the ActiveX * object oDoc:close() oWord:Quit() oWord:destroy() RETURN( cRet ) ////////////////////////////////////////////////////////////////////// Searches for a bookmark cBM by name in a given bookmark collection oBM, and assigns a new value cValue. ////////////////////////////////////////////////////////////////////// STATIC FUNCTION ReplaceBookmark( oBM, cBM, cValue ) LOCAL lRet := oBM:Exists(cBM), oF IF lRet oF := oBM:Item( cBM ) oF:Range:Text := cValue oF:Destroy() ENDIF RETURN(lRet) Naturalmente Il bookmark e' Univoco e lo posso duplicare piu' volte cambiando qualcosa tipo Nome1, Nome2, etc.. Questo se si sa' quante volte serve. La mia intenzione era dare un elenco dei campi_Rif che si possono usare all'utente finale e lui si costruisce il file in Word ed inserisce i riferimenti voluti, il problema e' alcuni campi_rif puo'/vuole usarli piu' volte, questo significa mettere mano alla procedura e duplicare i cam_rif interessati ogni volta che nasce l'esigenza dell'utente finale. Cioe' la prima volta gli basta usare il campo Cognome una volta , poi decide di usarlo una seconda volta nel testo (e creo Cognome2) , poi una terza (e creo Cognome3), poi .... Non mi va bene cosi'. ************* ESEMPIO 2 Via di Mezzo a Strtran ********** Esempio trovato su sito Tedesco Questo metodo sembra migliore ma ha una pecca e' un po' lento ( i primi due esempi sopra sono molto piu' veloci ) In un vettore carico i dati necessari Esempio : {"#Campo_Rif", "Valore da Sostituire"} {"#Cognome", "Rossi"} STATIC FUNCTION WordFillDocument( cFile, nF, aData, xPdf ) LOCAL oWord, oDoc, oWords, lSimbolo, i, nPos LOCAL cSave, cSavePdf, cDir, cRet := "", cX cDir := CurDrive() + ":\" + CurDir() cSave := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".DOC" cSavePdf := cDir + "\TEMP" + ALLTRIM( STR(nF) ) + ".PDF" oWord := CreateObject("Word.Application") IF Empty( oWord ) dbMsgW( "Microsoft Word NON Installato Su Questo PC" ) RETURN NIL ENDIF oWord := oWord:dynamicCast(ActiveXObject()) oWord:Visible := .F. *oWord:Visible := .T. oWord:documents:open(cFile, .F., .T.) oDoc := oWord:ActiveDocument oWords := oDoc:Words lSimbolo := .F. FOR i := 1 to oWords:Count * --- Cosa Cercare -> # + Parola cX := "#" + ALLTRIM( oWords:Item(i):Text ) * --- Scansione per Ricerca Simbolo # nPos := ASCAN( aData, {|aVal| aVal[1] == cX } ) * --- Se Trovato if lSimbolo .AND. nPos > 0 *DBMSGW(aData[nPos,1] + " " + aData[nPos,2], oWords:Item(i):Text) * --- Sostituzione Variabile con Testo oWords:Item(i):Text := aData[nPos,2] + " " * --- Rimuove # dal Testo Rimpiazzato oWords:Item(i-1):Text := "" endif * --- Imposta Simbolo lSimbolo := oWords:Item(i):Text == "#" NEXT * --- Ritorno nome di file generato cRet := cSave oDoc:saveas( cSave ) * --- Crea File Pdf IF xPdf == "X" oDoc:ExportAsFixedFormat( cSavePdf, 17 ) cRet := cSavePdf ENDIF * oWord:Visible := .t. * oWord:Application:Activate() oDoc:close() oWord:Quit() oWord:Destroy() dbMsgW( "Conversione Completata" ) RETURN( cRet ) ************* Considerazioni : Con bookmark e' veloce, l'utente si puo' gestire il file (word) da creare e piazzare i campi_riferimenti (da una lista campi che genera il programma) ma se si usa il campo piu' volte devo intervenire nel sorgente per duplicare il campo e inserirlo nella lista. Con Strtran e' veloce, l'utente si puo' gestire il file (word) da creare e piazzare i #Campi# (da una lista campi che genera il programma) anche piu' volte con lo stesso nome ma ha volte non vengono sostituiti (?) per risolvere il problema devono aprire il file (word) e spostare o reimpostare il campo che non viene sostituito risalvare e funziona. Con Esempio 2 funziona tutto ma e' piu lento rispetto ai primi due metodi. Altre idee ben accette. | |
Solving | Re: Uso di Word e BookMark (Segnalibri ) on Tue, 28 Oct 2014 19:37:00 +0100 ciao Mi sembra l'esempio 2 piu' macchinoso, perche' devo sdoppiare i campi in CodArt01, CodArt02 etc... etc mentre l'esempio 2 funziona gia' con un solo campo CodArt anche se ripetuto piu' volte nel testo. Pero' mi hai dato un'idea : creo un file dbf di 2 campi : campo_rif, nr_campo campo_rif = campo che l'utente deve usare dove necessita, e di default il campo nr_campo = 0 Poi l'utente se ha necessita di usare il campo piu' volte modifica il valore di nr_campo ( cioe' lo pone = alle volte che usa il campo dentro il file testo, sapendo che escluso lo 0 deve crearsi tanti riferimenti/bookmaker con stesso campo_rif + nr. cioe' : campo_rif = nome nr_campo = 0 significa che nel file testo esiste un riferimento/bookmaker nome. campo_rif = nome nr_campo = 1 significa che nel file testo esiste un riferimento/bookmaker nome e nome1. campo_rif = nome nr_campo = 2 significa che nel file testo esiste un riferimento/bookmaker nome, nome1 e nome2. etc....... Cosi' se un domani voglio usare il campo nome 20 volte nello stesso testo, dovro' inserire riferimenti/bookmark da nome a nome19 nel file testo e nel file elenco campi basta mettere 20. Questo serve non al programma in se', ma a riempire/espandere il mio vettore che passo al modulo activex. quindi posso avere il vettore gia' pieno con : <nome>, <pippo> o <nome>, <pippo> <nome1>, <pippo> o <nome>, <pippo> <nome1>, <pippo> <nome2>, <pippo> o <nome>, <pippo> <nome1>, <pippo> <nome2>, <pippo> .. .. <nome19>, <pippo> etc... a questo punto uso l'esempio 1 quello con solo i bookmark che e' veloce come esecuzione. Ed io non manipolo troppo il sorgente. p.s. e' complicato ? Il 28/10/2014 12.26, Fabio Cavallone ha scritto: > Ciao, > poichè, a quanto ho capito, i bookmark utilizzabili sono definiti da te > (tipo CodArt, CodCli, RagSoc, ...) potresti concordare (col cliente) una > convenzione, del > del tipo CodArt = CodArt01= CodArt02, ecc... > > Magari, modifichi il tuo array di riferimento in {<nome bookmark>, > <lunghezza del nome>, <valore di riferimento>} > > aRifBookmarks := {<nome bookmark>, <lunghezza del nome>, <valore di > riferimento>} > oDoc:= oWord:ActiveDocument > nBookmarks := oDoc:Bookmarks:Count > FOR i := 1 TO nBookmarks > nPos := aScan( aRifBookmarks, {|x| > lower(x[1])==lower(left(oDoc:Bookmarks(i):Name, x[2]))}) > IF nPos > 0 > ReplaceBookmark( oDoc:Bookmarks(i), oDoc:Bookmarks(i):Name, > aRifBookmarks[nPos,3] ) > ENDIF > NEXT > > P.S. Tieni presente che ho scritto tutto "al volo", ma, tolte possibili > correzioni, la logica dovrebbe funzionare. > > Fabio | |
Fabio Cavallone | Re: Uso di Word e BookMark (Segnalibri ) on Wed, 29 Oct 2014 12:51:18 +0100 Ciao, la strada con i bookmark che ti ho indicato, non richiede "pre-determinazioni" dei nomi, basta avere nel tuo array { {"codArt", "valore"} } per poter utilizzare nel documento word bookmarks da "codArt" a "codArt_il_numero_che_ti_pare"... (codArt, codArt01,CodArt001, CodArt97521358745687) a discrezione del cliente Fabio "Solving" ha scritto nel messaggio news:653d99e$11f21093$b3df@news.alaska-software.com... ciao Mi sembra l'esempio 2 piu' macchinoso, perche' devo sdoppiare i campi in CodArt01, CodArt02 etc... etc mentre l'esempio 2 funziona gia' con un solo campo CodArt anche se ripetuto piu' volte nel testo. Pero' mi hai dato un'idea : creo un file dbf di 2 campi : campo_rif, nr_campo campo_rif = campo che l'utente deve usare dove necessita, e di default il campo nr_campo = 0 Poi l'utente se ha necessita di usare il campo piu' volte modifica il valore di nr_campo ( cioe' lo pone = alle volte che usa il campo dentro il file testo, sapendo che escluso lo 0 deve crearsi tanti riferimenti/bookmaker con stesso campo_rif + nr. cioe' : campo_rif = nome nr_campo = 0 significa che nel file testo esiste un riferimento/bookmaker nome. campo_rif = nome nr_campo = 1 significa che nel file testo esiste un riferimento/bookmaker nome e nome1. campo_rif = nome nr_campo = 2 significa che nel file testo esiste un riferimento/bookmaker nome, nome1 e nome2. etc....... Cosi' se un domani voglio usare il campo nome 20 volte nello stesso testo, dovro' inserire riferimenti/bookmark da nome a nome19 nel file testo e nel file elenco campi basta mettere 20. Questo serve non al programma in se', ma a riempire/espandere il mio vettore che passo al modulo activex. quindi posso avere il vettore gia' pieno con : <nome>, <pippo> o <nome>, <pippo> <nome1>, <pippo> o <nome>, <pippo> <nome1>, <pippo> <nome2>, <pippo> o <nome>, <pippo> <nome1>, <pippo> <nome2>, <pippo> .. .. <nome19>, <pippo> etc... a questo punto uso l'esempio 1 quello con solo i bookmark che e' veloce come esecuzione. Ed io non manipolo troppo il sorgente. p.s. e' complicato ? Il 28/10/2014 12.26, Fabio Cavallone ha scritto: > Ciao, > poichè, a quanto ho capito, i bookmark utilizzabili sono definiti da te > (tipo CodArt, CodCli, RagSoc, ...) potresti concordare (col cliente) una > convenzione, del > del tipo CodArt = CodArt01= CodArt02, ecc... > > Magari, modifichi il tuo array di riferimento in {<nome bookmark>, > <lunghezza del nome>, <valore di riferimento>} > > aRifBookmarks := {<nome bookmark>, <lunghezza del nome>, <valore di > riferimento>} > oDoc:= oWord:ActiveDocument > nBookmarks := oDoc:Bookmarks:Count > FOR i := 1 TO nBookmarks > nPos := aScan( aRifBookmarks, {|x| > lower(x[1])==lower(left(oDoc:Bookmarks(i):Name, x[2]))}) > IF nPos > 0 > ReplaceBookmark( oDoc:Bookmarks(i), oDoc:Bookmarks(i):Name, > aRifBookmarks[nPos,3] ) > ENDIF > NEXT > > P.S. Tieni presente che ho scritto tutto "al volo", ma, tolte possibili > correzioni, la logica dovrebbe funzionare. > > Fabio | |
Solving | Re: Uso di Word e BookMark (Segnalibri ) on Tue, 04 Nov 2014 08:23:14 +0100 Altro Metodo : ******************************************************* oWord := CreateObject("Word.Application") IF Empty( oWord ) dbMsgW( "Microsoft Word NON Installato Su Questo PC" ) RETURN NIL ENDIF oWord := oWord:dynamicCast(ActiveXObject()) oWord:Visible := .F. oWord:documents:open(cFile, .F., .T.) oDoc := oWord:ActiveDocument oSele := oWord:ActiveDocument:content FOR i := 1 to LEN( aData ) oSele:Find:Execute(aData[i,1],.T.,,,,,,,,aData[i,2],2) NEXT * --- Save the resulting Word document cRet := cSave oDoc:saveas( cSave ) ETC.... *************************************** |