access stampa unione e invio mail personalizzate in pdf

Anonimo
2017-01-13T11:39:27+00:00

Buongiorno a tutti.

E' un po' di tempo che cerco di risolvere questo problema; ho letto, studiato e cercato di applicare al mio caso specifico decine di soluzioni in merito, ma, mancandomi quasi completamente le basi, non riesco nell'intento. Entriamo nel merito:

Lavoro periodico: capita spesso in studio di dover inviare delle lettere circolari personalizzate ai clienti; ho quindi creato un file di word generico "Stampa unione" con campi unione prelevati da una tabella di Access;

Obiettivo: inviare un file PDF personalizzato per ogni cliente come allegato ad una mail e salvare i files Pdf creati in apposita directory (va bene anche un unico file);

Procedura: da una maschera di Access apro il file di word "stampa unione" (pulsante con collegamento ipertestuale ?), lo salvo in una cartella predefinita con un nome specifico (esempio: "Nuove scadenze 2017"); completo il testo del file di word; torno in Access e con un pulsante invio le mail ai singoli destinatari con gli allegati PDF.

Tra le altre cose ho provato ad adattare quanto proposto da Maurizio Capannoli nella sua "Stampa unione e VBA: creare PDF e inviarli via email " ma restituisce una serie di errori che non riesco a superare.

Confido nel vostro prezioso aiuto e ringrazio fin da ora.

Buon week end a tutti.

Andrea Lucca

Microsoft 365 e Office | Access | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2017-03-02T20:10:16+00:00

ciao Andrea,

se non ci mostri la modifica alla routine come facciamo...? :-)

prova come segue :

      CreateEmailWithOutlook Rs.Fields("Mail"), strsubject, strMessaggio, strFile, CStr(Rs.Fields("ID_clienti"))

passa alla routine che crea l'email l'idcliente.

e modifica come segue la routine CreateEmailWithOutlook  ( in grassetto le modifiche) :

Option Compare Database

    Option Explicit

    Private outLookIstance As Object 'Outlook.Application

    Private Const strPathDichiarazione  As String = "E:\tuoPathSecondoFilePdfDaAllegare" '<<<< personalizzare

Public Function CreateEmailWithOutlook( _

    ByVal MessageTo As String, _

    ByVal Subject As String, _

    ByVal MessageBody As String, _

    ByVal strFile As String, _

    ByVal strID As String)

    ' Define app variable and get Outlook using the "New" keyword

    Dim olMailItem As Object ' Outlook.MailItem  ' An Outlook Mail item

Dim strSecondAtt As String

    ' Create a new email object

        newOlIstance

        Set olMailItem = outLookIstance.CreateItem(0)

    ' Add the To/Subject/Body to the message and display the message

        With olMailItem

            .To = MessageTo

            .Subject = Subject

            .Body = MessageBody

            .Display    ' To show the email message to the user

            .attachments.Add strFile

             strSecondAtt = strPathDichiarazione & "2016" & strID & ".pdf"

If fileExists(strSecondAtt) Then

.attachments.Add strSecondAtt

End If

        End With

        emailFocus2 Subject

    ' Release all object variables

    Set olMailItem = Nothing

End Function

e aggiungi questa funzione che controlla se il file esiste.

Private Function fileExists(ByVal strFile As String) As Boolean

On Error Resume Next

fileExists = (GetAttr(strFile) And vbDirectory) = 0

End Function

se esiste lo alleghi altrimenti no.

la modalità di creazione del strSecondAtt è brutta perché ho preso come riferimento la costante 2016 per l'anno 2016...le costanti sono il male come dicono i veri developers (io faccio mia questa loro indicazione) se devi allegare file dell'anno corrente meglio qualcosa del tipo :

strSecondAtt = strPathDichiarazione & format$(vba.date,"yyyy") & strID & ".pdf"

se invece la scelta dell'anno dovesse dipendere da altro si può ragionare diversamente....

Facci sapere.

ciao, Sandro.

La risposta è stata utile?

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2017-01-14T13:51:38+00:00

ciao Andrea,

[...]

Ti ringrazio per il complimento circa la pazienza e la buona volontà ! E' vero, quelle non mi mancano, purtroppo mi manca la conoscenza delle basi, in particolare ho una spiccatissima ed innata avversione per i cicli !!!!!

[...]

:-)

[...]

  • non tiene conto della condizione "clienti.invio = true";

[...]

secondo me si invece.

[...]

  • non cicla il recordset ma si limita a creare il Pdf solo per il cliente selezionato !!!;

[...]

per come lo hai impostato devi ciclare il recordsetclone della form visto i parametri passati, ma forse ti è più facile utilizzare il recordset creato ad hoc, passando il campo del recorset, nel codice qui sotto capirai perché

[...]

  • a livello di invio mail non trova l'allegato; temo poi che se anche lo trovasse, così come strutturato, il codice non sarebbe in grado di allegare a ciascun cliente il proprio messaggio personalizzato.

In buona sostanza UNA SCHIFEZZA, anche se spero che tu apprezzi almeno un po' lo sforzo profuso !

[...]

no secondo me no, la logica è giusta e ti sei fermato ad un passo dalla meta.

non trovi l'allegato perché non passi il path correttamente.

[...]

  • ogni volta che faccio un invio accodo in una tabella i campi data, ID cliente, oggetto e path dell'invio fatto;
  • creo una maschera basata su quella tabella che mi permetta di cercare con l'ID cliente oppure con la data oppure con l'oggetto gli invii effettuati.

Ho capito bene ?

[...]

si è esattamente quello che intendo che ti lascio sviluppare in autonomia,

Ovvia che se hai qualche difficoltà siamo qua.

Ti lascio la routine modificata che salva il doc in pdf e crea l'email.

Mi sono limitato a nominare "scolasticamente" il nome del file in pdf con il nome del cliente.

Non vedrei male nominare il file con data in formato americano concatenando nome cliente o suo id, tanto poi con la form basata sulla tabella di cui alla parte che devi sviluppare se serve il file lo individui facilmente.

Ricordati nell'automazione di word di chiudere l'istanza aperta e di distruggere le variabili oggetto, non sempre access fa il suo dovere ( con l'istanza la distruzione deve essere esplicita) nel resettare tutto a fine routine quindi diamogli una mano :-)

L'idea di utilizzare una funzione esterna per la gestione dei bookmarks è buona, non l'ho seguita perché a mio avviso il codice appare ordinato e lineare anche popolando i bookmarks nella routine esistente.

Personalizza il nome dei controlli....comando15...! ed inserisci una gestione errori.

prova la routine che segue :

Private Sub Comando15_Click()

    Dim Rs As DAO.Recordset

    Set Rs = CurrentDb.OpenRecordset("SELECT * FROM clienti WHERE clienti.invio = True ", dbOpenDynaset)

    Dim Wrd As Object, Doc As Object

    Dim Modello As String, NomeFile As String, i As Integer

    Dim Record As String, sql As String

    Dim PercorsoFile As String

    Dim PercorsoPdf As String

    Dim strMessaggio As String

    Dim strsubject As String

     PercorsoFile = "\DS1515PLUS\DatiAziendali\stampa unione"

     PercorsoPdf = "\DS1515PLUS\DatiAziendali\stampa unione\stampe pdf"

     NomeFile = "stampa unione modello demo.dotx"

     NomeDocWord = PercorsoFile & NomeFile

     'NomePDF = PercorsoPdf & Trim(Me.Nome) & "prova.pdf"

     strsubject = "Comunicazione"

     'strFile = PercorsoPdf

     On Error Resume Next

     Set Wrd = GetObject(, "Word.Application")

        If Err.Number = 429 Then

            Set Wrd = CreateObject("Word.Application")

        End If

     On Error GoTo 0

     On Error GoTo errHandler

     Wrd.Visible = False

     'Wrd.Activate

     'ReplSel = Wrd.Options.ReplaceSelection

     'Wrd.Options.ReplaceSelection = True

     Do Until Rs.EOF

            Set Doc = Wrd.Documents.Add(NomeDocWord)

            'Doc.Activate

            strMessaggio = "Gentile " & Rs.Fields("Nome") & vbNewLine

            With Doc.bookmarks

                .Item("nome").Range.Text = Rs.Fields("Nome")

                .Item("indirizzo").Range.Text = Rs.Fields("Indirizzo")

                .Item("frazione").Range.Text = Rs.Fields("Frazione")

                .Item("cap").Range.Text = Rs.Fields("Cap")

                .Item("città").Range.Text = Rs.Fields("Città")

                .Item("mail").Range.Text = Rs.Fields("Mail")

             End With

             strFile = PercorsoPdf & Rs.Fields("nome")

             With Doc

                .saveas FileName:=strFile, _

                        FileFormat:=17   ' wdFormatPDF

                .Close SaveChanges:=False

            End With

            strMessaggio = strMessaggio & "In allegato trasmettiamo la comunicazione in oggetto." & vbNewLine & "Distinti saluti" & vbNewLine & "Studio Pinco pallino."

            CreateEmailWithOutlook Rs.Fields("Mail"), strsubject, strMessaggio, strFile & ".pdf"

            Rs.MoveNext

       Loop

     'Call StampaBookmark(Doc, Wrd, "nome", Me.Nome)

     'Call StampaBookmark(Doc, Wrd, "indirizzo", Me.Indirizzo)

     'Call StampaBookmark(Doc, Wrd, "frazione", Me.Frazione)

     'Call StampaBookmark(Doc, Wrd, "cap", Me.Cap)

     'Call StampaBookmark(Doc, Wrd, "città", Me.Città)

     'Call StampaBookmark(Doc, Wrd, "mail", Me.Mail)

ExiterrorHandler:

    Rs.Close

    Set Rs = Nothing

    Set Doc = Nothing

    Wrd.Quit

    Set Wrd = Nothing

    Exit Sub

errHandler:

  With Err

        MsgBox "ERR#" & .Number _

             & vbNewLine & .Description _

             , vbOKOnly Or vbCritical

  End With

  Resume ExiterrorHandler

End Sub

Ciao, Sandro.

La risposta è stata utile?

0 commenti Nessun commento

70 risposte aggiuntive

Ordina per: Meno recente
  1. Anonimo
    2017-01-13T16:48:03+00:00

    ciao Andrea,

    certo si, intendevo proprio che tu pubblicassi il risultato della tua demo non funzionante.

    Pubblica condividi e posta il link o i due link, database e modello di word, in modo che vediamo e testiamo.

    [...]

    In effetti ho notato che nel codice "DocName" non è stato definito: ho scritto un'eresia ?

    [...]

    beh, no, eresia no, ma forse non hai settato l'oggetto o non valorizzato chi lo sa...! senza vedere nulla come si fa...

    [...]

    Grazie per la pazienza

    Andrea Lucca

    [...]

    prego.

    Ciao, Sandro.

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2017-01-13T17:23:50+00:00

    Grazie a tutti e due.

    Allego il file di word con la macro "scopiazzata" 

    https://1drv.ms/w/s!AoS1f\_man2ULhqd06A0iYjs4eBssVA

    e la base dati per la stampa unione

    https://1drv.ms/u/s!AoS1f\_man2ULhqd15Pztm2vk53UCVg

    e approfitto per chiedervi se, secondo il vostro parere, la procedura di lavoro corretta potrebbe essere la seguente:

    1. maschera di Access con cui seleziono i clienti interessati dalla comunicazione (già pronta grazie al vostro aiuto);
    2. accodo i clienti selezionati in una tabella temporanea, che sarà la base dati per i bookmarks presenti nel file di Word;
    3. dalla maschera apro il file di Word "Stampa unione " che è sempre il solito e si trova sempre nella medesima path;
    4. da Word salvo il file in una cartella apposita per le lettere circolari destinate ai clienti nominandolo come l'oggetto della comunicazione da inviare e con la data dell'invio;
    5. torno nella maschera di Access e premendo un pulsante: a) creo i singoli PDF che saranno allegati alle mail personalizzate indirizzati ai clienti selezionati al punto 1); b) creo un unico file PDF che contiene tutte le comunicazioni personali inviate ai vari clienti; c) invio le mail.

    Si accettano suggerimenti anche in merito alla procedura.

    Grazie

    Andrea Lucca

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2017-01-13T21:27:06+00:00

    ciao Andrea,

    I componenti la suite del pacchetto office permettono di aprire delle istanze l'una verso l'altra, in modo da poter sfruttare in un'applicazione gli oggetti dell'altra.

    La difficoltà è legata alla conoscenza degli oggetti dell'applicazione chiamata dalla chiamante cosa per niente intuitiva  a mio parere e non troppo semplice ma nemmeno così complessa.

    Nel tuo caso quindi devi creare un modello di word, non un file di word ma un modello, che conterrà i bookmarks.

    Da Access apri un'istanza verso word, apri un nuovo documento e popoli i bookmarks il file di word .doc con i dati provenienti da access, quelli che ha selezionato.

    Eviterei accodamenti in tabella temporanee o altro, con una form a visualizzazione maschera continue basta un flag ed un loop sul recordset della form stessa, ad ogni loop crei un documento e lo popoli.

    Il modello a oggetti di  word permette il salvataggio del file .doc in pdf, quindi nessuno salvataggio dapprima in doc e poi in pdf.

    Dopo averlo salvato il file crei un messaggio di posta elettronica con Outlook inserendo in allegato il file appena creato. Di questo ricordo sicuramente mie indicazioni in merito proprio a te.

    Tutta il processo può avvenire dietro le quinte nel senso che l'istanza creata di word può restare non visibile, e anche l'invio dell'email può avvenire senza dover effettuare alcun intervento.

    Con un click fai tutto.

    [...]

    a) creo i singoli PDF che saranno allegati alle mail personalizzate indirizzati ai clienti selezionati al punto 1); b) creo un unico file PDF che contiene tutte le comunicazioni personali inviate ai vari clienti;

    [...]

    se crei files pdf distinti forse non serve con altro file pdf con tutte le comunicazioni mi sembra un doppione.

    Potresti pensare di scrivere in una tabella in access la data di creazione del file, il suo path e l'id del cliente in modo da rintracciare la comunicazione o le comunicazioni a quel cliente.

    Bene, ora che ti ho indicato la strada, armati di pazienza e buona volontà, che non ti mancano, e prova ad imbastire qualcosa, nella demo che hai messo a disposizione non mi sembra ci sia un granchè.

    [...]

    Grazie

    Andrea Lucca   

    [...]

    prego, ciao.

    Sandro.

    La risposta è stata utile?

    0 commenti Nessun commento