Spedire circolari Outlook da indirizzari Excel
La tecnologia OLE Automation , detta anche sinteticamente Automation, permette proficui dialoghi fra applicativi. Si tratta di un sistema Client/Server dove il primo (Client) richiama la libreria del secondo (Server) utilizzandone proprietà e metodi.
Il codice macro che propongo deriva da una soluzione più completa dovuta a un mio corrispondente conosciuto tramite ShareOffice. Trattasi – onore al merito! – di Ettore Caliendo che tra l’altro sfrutta una caratteristica non a tutti ben nota: il formato HTML per il messaggio Outlook. Di conseguenza si può inglobare nel messaggio un’immagine, il logo della ditta nella fattispecie, mediante il tag (evidenziato in giallo, insieme ad altre particolarità, nella macro qui sotto riportata).
Il predetto Ettore all’inizio mi aveva palesato una perplessità, dovuta al fatto che tale logo non perveniva ai suoi corrispondenti. Per non sapere né leggere né scrivere (in tema di messaggi Outlook in formato HTML, lo confesso...) tuttavia gli ho subito detto: dovresti inserirla su un sito web, altrimenti come potrebbero gli estranei vedere la figura che risiede sul TUO PC?.
Compresa l’antifona, il rimedio è stato provato e andato in porto, con reciproca soddisfazione. Ed ecco, a beneficio delle masse, una Sub mutuata dal sullodato Ettore e un po' semplificata che va incorporata in un opportuno archivio Excel, tipo MessOutlook.xls, o MessOutlook.xlsm con Office 2010. Ho pensato di corredarla di due argomenti, il Cliente e l’IndirEmail di chiara semantica:
------------------
Sub MessHTML(Cliente As String, IndirEmail As String)
Dim Corpo As String
Dim Outlk As New Outlook.Application ' Early binding
Dim MioMess As Outlook.MailItem
Set MioMess = Outlk.CreateItem(olMailItem)
Corpo = "<html><body><p>"
Corpo = Corpo & "<img border='0' src='http://www.elicasrl.eu/loghi/logo_Elica.bmp'> "
Corpo = Corpo & " "
Corpo = Corpo & "<img border='0' src='http://www.elicasrl.eu/loghi/logo_Crif.bmp' ></p>"
Corpo = Corpo & "<p><font face='Tahoma' size='4'>Gentilissimo/a " & Cliente & ",<br>"
Corpo = Corpo & "la presente per richiederLe quanto segue: <br><br><br>"
Corpo = Corpo & "<br><br>"
Corpo = Corpo & "RingraziandoLa anticipatamente, Le porgiamo distinti saluti.<br><br>"
Corpo = Corpo & " Elica srl<br>"
Corpo = Corpo & " Rossi Asdrubale <br><br><br>"
Corpo = Corpo & "-------------------------------------------------------------------------<br>"
Corpo = Corpo & "TRAFFICI VARI srl<br>"
Corpo = Corpo & "Via Sette bellezze n. 103<br>"
Corpo = Corpo & "00123 Roma (RM)<br>"
Corpo = Corpo & "e-mail: settebell@gmail.it<br>"
Corpo = Corpo & "Tel. ******<br>"
Corpo = Corpo & "Fax ******<br>"
Corpo = Corpo & "web: www.settebell.com<br>"
Corpo = Corpo & "</font></p>"
Corpo = Corpo & "</body>"
With MioMess
.Subject = "Richiesta chiarimenti"
.Bcc = "pallino.pinco@lib.it"
.To = IndirEmail
.HTMLBody = Corpo
End With
MioMess.Send ' Invia il messaggio
' Libera le variabili “pesanti”:
Set MioMess = Nothing
Set Outlk = Nothing
End Sub
------------------
A ignari & immemori comincio col ricordare che per funzionare Automation chiede che nell'Editor VBA si fissino i riferimenti opportuni, mediante il comando Strumenti > Riferimenti... scegliendo poi Microsoft Outlook 12 Object Library nel nostro caso (diventa Outlook 14 con Office 2010).
Qui vale la pena di fare un paio di osservazioni. La prima è l’utilizzo della sintassi As New Outlook.Application, che al pregio della sinteticità unisce quello di fornire il cosiddetto Early Binding (associazione immediata) contrapposto al Late Binding (associazione tardiva) offerto invece dalla classica istruzione utilizzata dal nostro amico:
Outlk = CreateObject(“Outlook.Application”)
Nel qual caso la variabile è del tipo generale Object, con due conseguenze: maggior lentezza e segnalazione di errori solo a run-time, unita alla mancanza dell’intellisense. Infatti solo con l’early binding accanto al punto (.) della variabile Outlk spuntano, comodamente, cose come .Subject (l’oggetto del messaggio), .Bcc (il corrispondente in “carbon copy”, che può convenire assumere come il proprio email, per un riscontro, ovviamente al posto del comico e fantomatico pallino.pinco@lib.it!), .To IndirEmail (l’email del destinatario) e .HTMLBody = Corpo (il “corpo” del messaggio in formato HTML).
La seconda osservazione è il fatto che il buon Ettore ha impostato i riferimenti non a Microsoft Outlook bensì a Microsoft Office 12 (o 14 nell’edizione 2010), con un certo mio stupore! A caldo penso che questa sia più generale, ergo più “pesante” di quella che userebbe il sottoscritto. Ma non ne sono sicuro.
Nota. Posso però testimoniare che, in un’altra circostanza – Automation di Word – la libreria MS Office NON presentava una certa proprietà... Misteri dell’OLE Automation...
Tornando al testo del messaggio, a parte la sua genericità, che travalica il più squallido umorismo, esso dovrebbe essere chiaro a chiunque mastica il linguaggio HTML, faccio solo notare che con il concatenamento Gentilissimo & Cliente si ottiene l’inserimento del nome del destinatario nel corpo del messaggio stesso.
A questo punto, fatte le debite personalizzazioni, gl’interessati possono testare la predetta routine con un’istruzione del tipo seguente:
MessHTML "Michele Topo", topolino@disney.com
Più vantaggiosamente si può pensare a una serie di nominativi sul foglio Excel affiancati dai rispettivi indirizzi di posta elettronica:
Eccetera.
Immaginando, per estrema semplicità che i due dati siano collocati nelle colonne A e B a partire da A1, si potrebbe ricorrere alla procedura dell’evento BeforeDoubleClick:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Column <> 1 Or Target.Value = "" Then
Cancel = True ' Annulla il minieditor della cella
Exit Sub
End If
MessHTML Target.Value, Target.Offset(0, 1).Value
Cancel = True ' Annulla il minieditor della cella
End Sub
Che sul doppio click in una cella non vuota in colonna A lancia il massaggio Outlook a quel dato soggetto.
Nota ultimissima. In altri mondo OLE Automation si ha la proprietà Visible, che va impostata a True se si vuole che Excel o Word siano visualizzati, altrimenti agiscono nell’ombra. Nel caso Outlook Visible non esiste proprio. Poco male, perché l’applicativo può, indifferentemente, agire in background o allo scoperto, qualora fosse già aperto sulla nostra scrivania.
Mi fermo qui suggerendo agl’interessati altri esperimenti, in particolare un’applicazione di circolari più o meno standard, nel qual caso un opportuno ciclo del tipo For Each Nome In Indirizzario... Next sarà al centro del lavoretto o lavorone che ciascuno saprà implementare.
Ultim’ora: un’altra possibilità, anzi due
Questa variante mi è venuta in mente nel metrò (giuro). Consiste nell’uso della sintassi ; ; ... della casella A: (oppure Cc: o Ccn) che ha il vantaggio di registrare in Outlook un’unica missiva a più corrispondenti. Ed ecco la ricetta, che comprende due varianti. La prima consiste nel limitarsi al solo argomento IndirEmail della routine in questione:
(questo perché ora non è possibile specificare i singoli nominativi? ma più avanti vedremo che si può)
La seconda variante è un suggerimento, ovvero usare il metodo Save in luogo di Send. In tal modo si rimanda l’invio a tempi successivi, di tipo manuale ma con possibilità di adattamenti e/o ri-usi. Ed ecco il risultato:
Sub MessHTML(IndirEmail As String)
. . . idem c. s. . . .
With MioMess
.Subject = "Richiesta chiarimenti"
.Bcc = "pallinopinco@lib.it"
.To = IndirEmail
.HTMLBody = Corpo
.Save
End With
Set MioMess = Nothing
Set Outlk = Nothing
End Sub
Ciò premesso, ecco una possibile macro:
Sub Circolare()
Dim Indirizzi As String, PrimaCellaIndir As Range, i As Integer
Set PrimaCellaIndir = Range("PrimaCellaIndir")
Indirizzi = PrimaCellaIndir.Value
i = 2
While PrimaCellaIndir(i).Value <> ""
Indirizzi = Indirizzi & ";" & PrimaCellaIndir(i)
i = i + 1
Wend
MsgBox Indirizzi ' Da usare solo in fase di debug
MessHTML Indirizzi
End Sub
Ritengo che la ricetta parli da sola, dico solo che “PrimaCellaIndir” è il nome affibbiato alla prima cella dell’indirizzario, che sarà un campo in Colonna B o altrove.
E la seconda possibilità appena preannunciata? Dapprima non ci avevo pensato, ma è semplice. Consiste nell’utilizzare entrambi gli argomenti dell’iniziale routine MessHTML, passandole come secondo argomento una stringa di nominativi concatenati, tutti terminanti con
. Bando alle chiacchiere, fornisco la soluzione completa, che parte da una tabella Nomi/indirizzi come già vista:
La routine, ripetuta per comodità del lettore (ma la parte evidenziata è l’unica modifica):
Sub MessHTML(Cliente, IndirEmail As String)
Dim Corpo As String
Dim Outlk As New Outlook.Application
Dim MioMess As Outlook.MailItem
Set MioMess = Outlk.CreateItem(olMailItem)
Corpo = "
"
Corpo = Corpo & "
"
Corpo = Corpo & " "
Corpo = Corpo & "
"
Corpo = Corpo & "
Gentilissimi " & "
" & Cliente & "
"
Corpo = Corpo & "la presente per richiederLe quanto segue:
"
Corpo = Corpo & "
"
Corpo = Corpo & "RingraziandoLa anticipatamente, Le porgiamo distinti saluti.
"
Corpo = Corpo & " Elica srl
"
Corpo = Corpo & " Rossi Asdrubale
"
Corpo = Corpo & "-------------------------------------------------------------------------
"
Corpo = Corpo & "TRAFFICI VARI srl
"
Corpo = Corpo & "Via Sette bellezze n. 123
"
Corpo = Corpo & "00123 Roma (RM)
"
Corpo = Corpo & "e-mail: settebell@gmail.it
"
Corpo = Corpo & "Tel. ******
"
Corpo = Corpo & "Fax ******
"
Corpo = Corpo & "web: www.settebell.com
"
Corpo = Corpo & "
"
Corpo = Corpo & ""
With MioMess
.Subject = "Richiesta chiarimenti"
.Bcc = "giannigiac@tin.it"
.To = IndirEmail
.HTMLBody = Corpo
MioMess.Save
End With
' MioMess.Send ' Alternativa possibile
Set MioMess = Nothing
Set Outlk = Nothing
End Sub
La macro connessa a un opportuno pulsante Activex:
Private Sub CommandButton1_Click()
Dim ZonaNomi As Range, Iniz As Range
Set Iniz = Range("InizNomi")
With Iniz
Set ZonaNomi = Range(.Cells(1), .End(xlDown))
End With
Dim Nomi As String, Indirizzi As String, i As Integer
Nomi = Iniz.Value & "
"
Indirizzi = Iniz.Offset(0, 1).Value
For i = 2 To ZonaNomi.Count
Nomi = Nomi & ZonaNomi(i).Value & "
"
Indirizzi = Indirizzi & ";" & ZonaNomi(i).Offset(0, 1).Value
Next
MessHTML Cliente:=Nomi, IndirEmail:=Indirizzi
End Sub
Meditate il ciclo in giallo, gente e vedrete che funziona.
?>
?>
?>
?>