Inserire intervalli Excel in messaggi Outlook
Un visitatore mi ha mandato questa richiesta:
È possibile una macro che inserisca nel corpo di un messaggio Outlook un intervallo di Excel?
Risposta. Sicuramente. A due condizioni (che poi si riducono a uno stesso principio).
1) Che, nella cartella di lavoro da cui si parte, vengano fissati i riferimenti ad Outlook;
2) Che, nella stessa cartella si fissino i riferimenti a Word.
La prima è scontata, direi, mentre alla seconda non tutti pensano. Il fatto è che – e qui accenno subito al trucco fondamentale (che, peraltro, ho già suggerito in un precedente post, dedicato a Outlook:
http://blog.shareoffice.it/giannigiaccaglini/archive/2006/09/25/7739.aspx) –
solo con Word è possibile incollare una zona Excel in un documento, anche se si lavora in Outlook.
Nota – Di regola, Outlook 2003 opera “in simbiosi” con Word, ma se si parte da Excel si direbbe che se ne dimentichi. Provare per credere a non fissare i predetti riferimenti nella macro che sto per svelare…
Ai principianti ricordo le mosse per i dannati riferimenti. 1. Passare all’Editor VB con Alt+F11; 2. Scegliere Strumenti > Riferimenti…; 3. Nella susseguente dialog box spuntare la casellina necessaria; 4. Concludere con OK.
Venendo alla soluzione, ecco un banale caso di intervallo Excel, con tanto di formati che, naturalmente, vorremmo fossero conservati:
|
Articolo |
Quantità |
Prezzo |
Importo |
|
Mele |
14,00 |
€ 2,00 |
€ 28,00 |
|
Susine |
13,00 |
€ 3,00 |
€ 39,00 |
|
Banane |
11,00 |
€ 1,50 |
€ 16,50 |
|
Pere |
13,00 |
€ 3,00 |
€ 39,00 |
|
Pesche |
10,00 |
€ 2,75 |
€ 27,50 |
|
Arance |
12,00 |
€ 2,90 |
€ 34,80 |
|
Mandarini |
15,00 |
€ 3,05 |
€ 45,75 |
|
Limoni |
16,00 |
€ 3,20 |
€ 51,20 |
Ed ecco la sospirata macro, con argomenti:
Sub MessaggioConZona(Zona As Range, Destin As String)
'Con inserimento dell'intervallo Zona nel corpo di un messaggio
Dim OutlkApp As Outlook.Application, Nms As Outlook.Namespace
Set OutlkApp = Outlook.Application
Set Nms = OutlkApp.GetNamespace("MAPI")
Dim MioMess As MailItem
Set MioMess = OutlkApp.CreateItem(olMailItem)
With MioMess
.BodyFormat = olFormatRichText
.To = Destin
.Body = " " 'Istruzione forse superflua
.Display
End With
Zona.Copy
ActiveDocument.Range.Paste
Application.CutCopyMode = False
Set MioMess = Nothing
Set Nms = Nothing
End Sub
Commenti essenziali. Inizialmente si imposta, in OutlkApp l’oggetto che corrisponde all’applicazione Ouutlook e in Nms il Namespace “MAPI” (non vi scervellate a capire cos’è esattamente: questa istruzione è obbligatoria ogni volta che si devono usare i particolari archivi di Outlook), si crea un nuovo messaggio MioMess con:
Set MioMess = OutlkApp.CreateItem(olMailItem)
A tale MioMess si applica il formato RTF, si assegna l’indirizzo e-mail Destin(atario), poi lo si visualizza col metodo Display. Il lavoro si conclude applicando il metodo Copy alla Zona, l’intervallo passato come primo argomento e subito dopo incollandolo dagli Appunti nel documento attivo (.Range.Paste) che poi è il corpo del nostro messaggio.
Si potrebbe, almeno nei casi sicuri, fare a meno di Display e inviare (Send) il messaggio:
MioMess.Send
Ma con Display l’utente ha modo di vedere un risultato parziale, che può magari completare prima di spedirlo tramite comando amanuense.
Ecco infine una possibile routine di test:
Sub Prova()
MessaggioConZona Range("A1:D9"), "pinco@pallino.it"
End Sub
Il bello della faccenda è che tutti i formati, come i grassetti, le cornici e le zebratura dell’esempietto vengono conservati, ma ovviamente le formule vanno perse (d’altronde entrambe le cose, come tutti sanno, accadono copiando e incollando intervalli Excel in documenti Word).
Un ulteriore perfezionamento
Potrebbe essere il seguente:
Sub MessaggioConZona(Zona As Range, Destin As String, Oggetto As String)
'Con inserimento dell'intervallo Zona nel corpo
Dim OutlkApp As Outlook.Application, Nms As Outlook.Namespace
Set OutlkApp = Outlook.Application
Set Nms = OutlkApp.GetNamespace("MAPI")
Dim MioMess As MailItem
Set MioMess = OutlkApp.CreateItem(olMailItem)
With MioMess
.BodyFormat = olFormatRichText
.To = Destin
.Subject = Oggetto
.Body = "Ecco i dati aggiornati:"
.Display
End With
Zona.Copy
'Seleziona il documento attivo (il Body del nuovo messaggio)
ActiveDocument.Select 'Activate NON va!
With Word.Selection '"Word." necessario, pena conflitto con oggetto Selection di Outlook
.EndKey Unit:=wdStory 'Va a fine documento
.TypeParagraph 'Inserisce un Carriage return
.TypeParagraph 'Inserisce un altro " "
.Range.Paste
End With
Application.CutCopyMode = False
Set MioMess = Nothing
Set Nms = Nothing
End Sub
La relativa routine di prova? Eccola:
Sub CreaMessaggio()
MessaggioConZona Range("A1:D15"), "giocond@giocondor.it", "Fatturato Ortofrutta"
End Sub
E una soluzione ultrarapida (con intervento finale amanuense)
Parte dalla constatazione che se in una cella è presente un indirizzo e-mail, un clic su tale cella crea al volo una letterina Outlook con quell'indirizzo nel campo specifico e con gli altri campi vuoti. Ho allora pensato di sfruttare l'evento FollowHyperlink dell'ipotetico Foglio1 in cui immagino esista un intervallo di nome "DatiOrtofrutta" da spedire a quel tal giocondo@giocondor.it::
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Range("DatiOrtofrutta").Copy
End Sub
Tutto qui? Sì perché in questo caso interferire col messaggio creato automaticamente si direbbe arduo (se qualcuno ci riesce me lo dica!). Ma l'utente scafato sa bene cosa gli resta da fare :
- Passare ad Outlook (ma magari è già aperto);
- Nel testo del neonato messaggio digitare qualcosa come "Ecco i dati del... cavolo";
- premere Ctrl+V, per prelevarli dagli Appunti.
?>
?>
?>