Spedire da Excel il foglio di lavoro come attachment Outlook
Un visitatore di Shareoffice mi ha posto il seguente quesito.
Problema. Ho preparato un questionario con Excel che distribuirò via e-mail. Vorrei inserirvi un pulsante connesso a una macro che consenta a ciascuno di rispedirmi un e-mail con il file .XLS in allegato. Qual è il codice necessario?
La sfida è interessante, anche se di tipo complesso, in quanto chiama in gioco sia Excel che Office Outlook, con la pochissimo nota tecnica (OLE) Automation. La soluzione, in linea di massima, sembra possibile, però nel caso specifico vanno subito messi in evidenza rischi vari:
v alcuni corrispondenti del nostro amico potrebbero possedere solo Outlook Express o, peggio altri client e-mail, nel qual caso la parte di macrocodice VBA per l'ambiente MS Outlook fallirebbe;
v altri potrebbero avere impostato il livello ELEVATO di protezione delle macro, per cui quelle tali belle macro NON gli funzionerebbero;
v si possono presentare ulteriori inghippi, su cui non mi dilungo.
In breve la cosa migliore, nel caso di un coinvolgimento “pubblico”, consiste nell’inviare a ciascuno il modello con chiare indicazioni su come compilarlo e salvarlo e, infine, spedirlo come attachment all’indirizzo e-mail del… sondaggista. Queste operazioni le sanno fare tutti gli utenti, che diamine.
Non nascondo poi la difficoltà del problema, espressa dalla seguente domanda:
Come fare a spedire in allegato a una e-mail l’attuale file Excel che incorpora neanche a farlo apposta la macro cui è affidato questo compitino?
Sembra facile… Comunque, pensa e ripensa, ho poi trovato un marchingegno che permette la soluzione, che naturalmente può aver senso se si rivolge a una ben precisa comunità di gente, che tra l'altro: a) usa e non disabilita le macro VBA e b) possiede Microsoft Outlook; c) nell’Editor VBA lancia Strumenti > Riferimenti… fissando quelli a Outlook (versione 11, con Office 2003), altrimenti la tecnica Automation non funziona proprio.
Ecco la ricetta
In termini essenziali il codice è riportato qui di seguito. L’idea è quella di un responsabile di un qualche gruppo aziendale o di altro genere (club e simili) che invia ai sottoposti uno schema posto su un foglio di lavoro, con preghiera di rimandarlo con dati opportuni. La macro si trova appunto incorporata proprio su tale cartella Excel.
Sub SalvaEInvia()
Dim Percorso As String, NomeFile As String
With ThisWorkbook
Percorso = .Path
ChDir Percorso
NomeFile = .Name
Application.DisplayAlerts = False
.SaveAs "TEMP" & NomeFile 'Salva il file con un nome preceduto da "TEMP"
End With
'Qui comincia l’avventura, con Outlook-Bonaventura:
Dim Outlk As New Outlook.Application 'Apre un’istanza di MS Outlook
Dim MioMess As MailItem
'Imposta una letterina Outlook...
Set MioMess = Outlk.CreateItem(olMailItem)
'... e ne stabilisce gli estremi
With MioMess '
.To = "pallinodettopinco@libero.it"
.Subject = "Invio della solita relazione vendite
.Body = "Trentatrè Trentini venivano giù da Trento"
.Attachments.Add Percorso & "\" & NomeFile 'NON dimenticare la "\" !!!
.Display 'Visualizza il messaggio
'.Send 'ISTRUZIONE EVENTUALE PER SPEDIRE IL MESSAGGIO
End With
'Libera le variabili-oggetto (istruzione qui facoltativa)
Set MioMess = Nothing
Set Outlk = Nothing
End Sub
Commenti. Le istruzioni iniziali servono a fissare la directory in cui si trova il file .XLS (Path) tramite ChDir, poi ne viene salvata una copia, preceduta da “TEMP” (così se putacaso il file si chiama Rendiconto.XlS il suo doppio sarà TEMPRendiconto.XlS, registrato nella stessa cartella di file. Interessante la proprietà DisplayAlerts = False, che fa sì che il secondo file vada a sostituire un’eventuale copia precedente senza proteste, evitando così proliferazioni (e facilitando la eliminazione di quest’unico oggetto superfluo).
Nota - Le persone non distratte constateranno poi che la macro prosegue senza inghippi per il semplice fatto che anche il file salvato nuovo continua regolarmente a incorporarla!
Circa l’uso di Outlook ritengo che il relativo codice sia parlante, per cui sottolineo solo che l’aver, in apertura, memorizzato sia il Percorso che il Nome dell’originario si è reso necessario per il fatto che Attachements.Add pretende un pathname completo ( o no?).
Alla fine dei conti: il trucco c’è, e si vede: il salvataggio di una copia (in sé fasulla) dell’ipotetico Rendiconto.xls ossia del file principale fa sì che questo rimanga sul disco e, di conseguenza, si possa allegare nell’e-mail ritornato al mittente.
Una routine abbastanza generale (già che ci siamo)
Supponiamo, per fissare le idee, che si debbano spedire abbastanza regolarmente delle circolari e-mail di argomento e oggetto fisso a corrispondenti variabili e con allegati eventuali pure in numero vario. Si potrebbe pensare alla seguente Sub con argomenti:
Sub InvioRelazione(Destinatari As String, _
ConAllegati As Boolean, Allegati As String
Dim Outlk As New Outlook.Application
Dim MioMess As MailItem
'Imposta una letterina Outlook...
Set MioMess = Outlk.CreateItem(olMailItem)
'... e ne stabilisce gli estremi
With MioMess '
.To = Destinatari
.Subject = "Relazione"
.Body = "Inviamo alle SS. LL. il rendiconto..."
If ConAllegati Then .Attachments.Add Allegati
.Display 'Visualizza i vari messaggi
Set MioMess = Nothing
Set Outlk = Nothing
End With
End Sub
Ricordo a Ignari & Immemori che a proprietà To può essere una stringa di indirizzi “in chiaro” comunemente presenti nei Contatti di Outlook separati da punto e virgola. Pertanto un possibile richiamo della precedente procedura è subito visto:
InvioRelazione "Mario;Carmen;Pasquale;Giacomo", _
True, "C:\Documenti\Relazioni\Bilancio.xls”
Tale istruzione manda il messaggio con l’attachment Bilancio.xls ai quattro allegri soci. A individui meno simpatici (o raccomandati) un’analoga istruzione però ConAllegati:= False, fornirebbe solo una comunicazione, priva del file Excel.
Nota - Se si lavora solo in Outlook non va beninteso messa l’istruzione che lo richiama, inoltre si avrà Set MioMess = Application.CreateItem(...), ove Application è ora Outlook stesso, visto che in tale ambiente ci troviamo.
Segnalo infine che si potrebbe preparare la stringa Destinatari da passare come argomento alla routine in parola con un loop come il seguente, che attinge da un qualche elenco Excel “NomiContatti”, opportunamente filtrato:
For Each Cella In Range("NomiContatti")
Destinari = _
Destinatari & Cella.Value & ";"
Next
L’importante è che gl’indirizzi così concatenati siano coerenti coi Contatti presenti in Outlook.
Suggerimento (a buoni intenditori). Ricorrere al comando di esportazione Contatti, in formato Excel.
?>