› Sviluppare funzionalita su Microsoft Office con VBA › VBA – Non riesco a creare cicli e salvare in PDF
-
AutoreArticoli
-
Ciao a tutti. Sono Daniele, sono nuovo di questo forum e anche dei linguaggi di programmazione. Sto studiando il basic e sto avendo problemi con una macro che ho creato per velocizzare le operazioni in ufficio. In poche parole io ho un elenco di nomi e cognomi con dati personali di alcune persone che devono ricevere degli attestati di partecipazione. Ho creato un file word con l'attestato già pronto e ho aggiunto i 4 segnalibri (Nome, cognome, data di nascita e comune di nascita) che devo trasportare dal file excel. Sono riuscito a creare il VBA prendendo idee e modificando codici trovati in rete, ma ora non riesco a fare due cose: fare gli attestati per ogni riga (il mio codice riesce a generare un attestato alla volta) ed esportare gli attestati in formato pdf e non word. Vi allego il codice. Spero che mi sappiate aiutare. Grazie mille in anticipo.
Option Explicit
Public URec As Long
Public x As Byte
Const Path As String = "C:\Prove\Word\"
Const FileWord As String = "Baseok.docx"Sub Copia_su_Word()
On Error GoTo 10
Application.ScreenUpdating = False
Dim FileDoc As String
Dim wrdApp, wrdDoc
Dim I As Long
Const sFILENAME As String = Path & FileWord
If ActiveCell.Row < 6 Or ActiveCell.Row > Range("A" & Rows.Count).End(xlUp).Row Then End
FileDoc = Path & Cells(ActiveCell.Row, 5)
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
Set wrdDoc = wrdApp.Documents.Open(sFILENAME)
With wrdDoc
.Bookmarks("Cognome").Range.Text = Cells(ActiveCell.Row, 3) ' Cognome
.Bookmarks("Nome").Range.Text = Cells(ActiveCell.Row, 4) ' Nome"
.Bookmarks("Data").Range.Text = Cells(ActiveCell.Row, 7) ' Data"
.Bookmarks("Luogo").Range.Text = Cells(ActiveCell.Row, 6) ' Luogo"End With
wrdApp.ActiveDocument.SaveAs Filename:=FileDoc
wrdApp.Quit
Application.ScreenUpdating = True
Cells(ActiveCell.Row + 1, 3).Select
Application.ScreenUpdating = True
For I = 0 To 100
If Cells(I, 3) = "" Then
Exit Sub
End If
Cells(I, 2) = Cells(I, 1)
Next I
10:
End SubPer inserire del codice ben formattato puoi utilizzare il pulsante {;} che trovi nell'editor.
Vedo che hai usato Option Explicit: molto bene benissimo 🙂
Un'idea che suggerisco è di non usare dei segnalibri ma dei segnaposto: nel documento Word che agisce da modello inserisci del testo particolare che poi sostituirai coi dati reali.
Esempio:
Preg.mo @COGNOME @NOME
Poi con il ciclo nel range dei nominativi prelevi i valori di ogni riga che ti serve e con il metodo Find/Replace di Word sostituisci a @COGNOME il testo desiderato. Mi pare anche che abbiamo scritto un articoletto su questo, cerca nel blog del forum, dovresti trovarlo.
Per creare quanti attestati vuoi devi creare un ciclo For Next che parta dalla tabella in Excel e scorra le righe (quindi non ti riferirai più all'ActiveCell ma alla variabile contatore del ciclo), apri il file Word che fa da modello, sostituisci i valori che devi sostituire e salvi con nome anzi usi il metodo ExportAsFixedFormat dell'oggetto Document per avere il tuo bel pdf.
E' più semplice di quello che credi: io inizierei da una sub nuova, a creare lo scheletro del ciclo che scorre la tabella Excel. Tanto per cominciare da qualche parte. E cerca quell'articolo nel blog 🙂
Grazie per la risposta, ma purtroppo non sono molto ferrato in programmazione e non sono in grado di creare il ciclo for next che funzioni... so che devo impostarlo subito dopo la Open e lo devo concludere subito dopo la Save. Ho fatto delle prove, ma niente. Riusciresti a correggere il mio script e a farmi capire l'errore? Grazie mille
Per inserire del codice ben formattato puoi utilizzare il pulsante {;} che trovi nell'editor.
Grazie per la risposta, ma purtroppo non sono molto ferrato in programmazione e non sono in grado di creare il ciclo for next che funzioni... so che devo impostarlo subito dopo la Open e lo devo concludere subito dopo la Save. Ho fatto delle prove, ma niente. Riusciresti a correggere il mio script e a farmi capire l'errore? Grazie mille
Esaminando il codice mi saltano agli occhi degli errori concettuali da sradicare...
- evita quando puoi le variabili pubbliche, utilizza ove possibili variabili private (quindi non dichiarare niente fuori dai moduli se proprio non è necessario)
- non usare mai la parola chiave End, produce effetti strani, utilizza Exit Sub o Exit Function per terminare le procedure
- evita l'intercettazione degli errori e non usare etichette con numeri di riga (così se il programma si ferma puoi capire perchè e dove, e le etichette con numeri dicono poco)
- devi chiudere l'applicazione Word quando hai finito e devi annientare gli oggetti esterni con Set ... = Nothing alla fine del codice
non sono in grado di creare il ciclo for next che funzioni
Non ho provato a riprodurre lo scenario con file reali, ma a naso dovresti inserire il ciclo For prima dell'apertura del file modello (hai dichiarato l'oggetto Document, qui imposti il ciclo che apre il documento base, sostituisce i dati dei segnalibri, poi esporta in PDF e infine chiude il ciclo:
Option Explicit Public URec As Long Public x As Byte Const Path As String = "C:\Prove\Word\" Const FileWord As String = "Baseok.docx" Sub Copia_su_Word() Application.ScreenUpdating = False Dim Filename As String Dim wrdApp As Object, wrdDoc As Object Dim I As Long Dim ac As Long If ActiveCell.Row < 6 Or ActiveCell.Row > Range("A" & Rows.Count).End(xlUp).Row Then End Set wrdApp = CreateObject("Word.Application") wrdApp.Visible = True lastrow = Range("A" & Rows.Count).End(xlUp).Row For ac = 2 To lastrow Filename = Path & Cells(ac, 5) Set wrdDoc = wrdApp.Documents.Open(Filename & ".doc") With wrdDoc .Bookmarks("Cognome").Range.Text = Cells(ActiveCell.Row, 3) ' Cognome .Bookmarks("Nome").Range.Text = Cells(ActiveCell.Row, 4) ' Nome" .Bookmarks("Data").Range.Text = Cells(ActiveCell.Row, 7) ' Data" .Bookmarks("Luogo").Range.Text = Cells(ActiveCell.Row, 6) ' Luogo" End With wrdDoc.ExportAsFixedFormat Filename:=Filename & ".pdf", ExportFormat:=17 ' wdExportFormatPDF wrdDoc.Close False ' Cells(ActiveCell.Row + 1, 3).Select ' Application.ScreenUpdating = True For I = 0 To 100 If Cells(I, 3) = "" Then Exit Sub End If Cells(I, 2) = Cells(I, 1) Next I Next Application.ScreenUpdating = True wrdApp.Quit Set wrdApp = Nothing End Sub
Sono andato alla cieca, spero che sia tutto corretto, soprattutto non capisco a cosa ti servono le istruzioni finali del ciclo For I = 1 to 100.
Sono andato alla cieca, spero che sia tutto corretto, soprattutto non capisco a cosa ti servono le istruzioni finali del ciclo For I = 1 to 100.
Me le sono dimenticate da una prova fatta in precedenza. Comunque mi dice che la variabile lastrow non è stata definita.
Giusto, per fortuna c'è Option Explicit 🙂
Bè sai ovviare a questo no? Io intanto provo a costruirmi uno scenario, costruendomi dei file di prova (sempre se non li alleghi tu, il che non sarebbe una cosa così cattiva 😛 )
Bè sai ovviare a questo no? Io intanto provo a costruirmi uno scenario, costruendomi dei file di prova (sempre se non li alleghi tu, il che non sarebbe una cosa così cattiva )
Eccoli qui
Allegati:
You must be logged in to view attached files.Textomb?
Textomb?
Si, ho trovato questo file da un forum in cui stavo studiando il mio problema. Ho creato prima un mio file, ma questo era più completo, così l'ho modificato in base a quello che mi serviva. Ho mantenuto il nome originale.
Textomb è un grande. Peccato non vederlo più qui 🙂
Domani mi applico al tuo problema ma se vedi che passa troppo tempo e non mi senti più fammi n messaggio per dirmi svegliaaaaa 🙂
Textomb è un grande. Peccato non vederlo più qui
Domani mi applico al tuo problema ma se vedi che passa troppo tempo e non mi senti più fammi n messaggio per dirmi svegliaaaaa
Non lo conosco, ma ho seguito un suo forum e mi ha aiutato a capire molte cose. Grazie mille, sei stato fantastico. A domani.
Domani mi applico al tuo problema ma se vedi che passa troppo tempo e non mi senti più fammi n messaggio per dirmi svegliaaaaa
Ciao. Forse è un po' tardi, ma sono appena tornato a casa. Se hai tempo e voglia di aiutarmi sarebbe grandioso 🙂
Veramente non capisco che difficoltà hai incontrato. Funziona bene 🙂
Option Explicit Public URec As Long Public x As Byte Const Path As String = "C:\Prove\Word\" Const FileWord As String = "C:\Prove\Baseok-2.docx" Sub Copia_su_Word() Application.ScreenUpdating = False Dim Filename As String Dim wrdApp As Object, wrdDoc As Object Dim I As Long Dim ac As Long Dim LastRow As Long If ActiveCell.Row < 6 Or ActiveCell.Row > Range("A" & Rows.Count).End(xlUp).Row Then Exit Sub Set wrdApp = CreateObject("Word.Application") wrdApp.Visible = True LastRow = Range("A" & Rows.Count).End(xlUp).Row For ac = 6 To LastRow Filename = Path & Cells(ac, 5) Set wrdDoc = wrdApp.Documents.Open(ThisWorkbook.Path & "\" & FileWord) With wrdDoc .Bookmarks("Cognome").Range.Text = Cells(ac, 3) ' Cognome .Bookmarks("Nome").Range.Text = Cells(ac, 4) ' Nome" .Bookmarks("Data").Range.Text = Cells(ac, 7) ' Data" .Bookmarks("Luogo").Range.Text = Cells(ac, 6) ' Luogo" End With wrdDoc.ExportAsFixedFormat Filename & ".pdf", ExportFormat:=17 'wdExportFormatPDF wrdDoc.Close False Next Application.ScreenUpdating = True wrdApp.Quit Set wrdApp = Nothing End Sub
Veramente non capisco che difficoltà hai incontrato. Funziona bene
Si, funziona... solo che a me necessità premere un pulsante ed esportare non uno, ma tutti i dati che trova nella griglia e poi in PDF e non in doc
Set wrdDoc = wrdApp.Documents.Open(ThisWorkbook.Path & "\" & FileWord)
Su questo mi scrive "Necessario oggetto"
IL codice che ho postato fa proprio quello che chiedi: tutto accade nel ciclo For, dove viene aperto il file base, vengono inseriti i dati della prima riga, viene salvato il pdf (con nome il codice fiscale), il file base viene chiuso e si passa alla riga successiva dove il ciclo ricomincia. Ho ottenuto sette pdf, tante quante solo le righe del file di prova.
Su questo mi scrive "Necessario oggetto"
Bè ma è ovvio, io ho fatto le prove su percorsi miei, tu devi cambiare in base alle tue esigenze.
Sostituisci con questa riga:
Set wrdDoc = wrdApp.Documents.Open(FileWord)
Naturalmente il file in Word deve esistere nella cartella C:\prove.
Comunque coraggio, studiati il codice e per ogni istruzione che non capisci chiedi. Ma non fermarti al primo errore che incontri.
Naturalmente il file in Word deve esistere nella cartella C:\prove.
Comunque coraggio, studiati il codice e per ogni istruzione che non capisci chiedi. Ma non fermarti al primo errore che incontri.
Grazie di tutto. Ma è possibile che mi manca qualcosa nei riferimenti?
Ultima cosa. Se al posto del codice fiscale volessi nome e cognome? Perchè io riesco a far apparire solo o il nome o il cognome
Ma è possibile che mi manca qualcosa nei riferimenti?
In teoria nel codice c'è solo la tecnica detta late binding quindi gli oggetti vengono creati attraverso la loro class application, e non devi referenziare niente. Hai degli errori di qualche tipo?
Se al posto del codice fiscale volessi nome e cognome?
Intendi come nome di file? certo che puoi, perchè qui
Filename = Path & Cells(ac, 5)
imposti il nome del successivo file pdf al contenuto della cella di colonna 5 (che è la colonna "E"), la quale contiene il codice fiscale. Se vuoi nome e cognome ti basta concatenare il contenuto delle celle appropriate.
Cosa intendi con la frase successiva?
io riesco a far apparire solo o il nome o il cognome
Cosa intendi con la frase successiva?
Ecco. quello che non so è concatenare, ne so mettere solo uno e avevo scelto il codice fiscale perchè poteva capitare che c'erano più cognomi uguali.
FUNZIONAAAAA!!!
Se mi spieghi come concatenare nome e cognome ho finito
Concatenare significa mettere insieme. In VBA puoi usare l'operatore & (e-commerciale) per unire due stringhe di testo. Nel tuo caso hai cognome in colonna C e nome in colonna D.
Vedi come è fatta l'istruzione Filename = ...?
Applica lo stesso concetto per concatenare in modo opportuno i dati che ti servono (magari separandoli con uno spazio aggiuntivo tra i due).
Provaci e vediamo 🙂
Provaci e vediamo
Funziona tutto. Io non so davvero come ringraziarti. Sei stato fondamentale. Grazie grazie grazie
-
AutoreArticoli