Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Ron de Bruin
Microsoft Excel MVP
Frank C. Rice
Microsoft Corporation
August 2003
Applies to:
Microsoft® Excel 97 and later versions
Summary: Microsoft Excel MVP Ron de Bruin provides a number of samples and a handy add-in that enhances your experience when working with e-mail from Excel. From sending individual worksheets in a workbook to sending e-mail to multiple recipients, the code samples and add-in should become a part of your reference library. The SendMail 2.0 add-in and a user guide is available from http://www.rondebruin.nl. (13 printed pages)
Introduction
Sending E-Mail in Excel
Before You Send E-Mail
Send the Active Workbook by E-mail
Send a Single Sheet by E-mail
Send an Array of Worksheets by E-mail
Send the Selection by E-mail
Send Specific Worksheets by E-mail
Send Work Sheets to One or More People by E-mail
Tips for Changing the Examples
The SendMail 2.0 Utility
Conclusion
About the Authors
This article features code samples, a wizard, and an add-in utility that you can use to perform various e-mail functions from Microsoft Excel. Ron de Bruin, an Excel Most Valuable Professional (MVP) and a frequent contributor to the newsgroups provided the samples and add-in.
Note You should be aware of the two main security features for Outlook 2002 and later versions (and with a security patch for Outlook 2000):
- Blocking of a customizable list of file attachments considered unsafe because they can be used to propagate viruses.
- Pop-up confirmation dialogs that occur whenever a program accesses address-related properties or attempts to send a message.
These constraints can affect the way you interact with Outlook in the following procedures.
One way to send e-mail from Excel is to the use the Mail Merge Wizard which is only available in Excel 2000 and later versions (called the Mail Merge Helper in Excel 2000). The Mail Merge Wizard simplifies the batch creation of letters, sending of e-mail messages, creating postal mailing labels, labeling envelopes for postal mail, and creating directory lists. You can find more detailed information about the Mail Merge Wizard by reading the Excel help topic titled Create a Word mail merge with Excel data.
Another way to use the e-mail features of Excel are with the code samples discussed in this article. In addition to augmenting your own code, you can use the samples provided here as a starting point to better help you understand how you can send as e-mail the various objects and data in your own worksheets and workbooks. Several samples also include alternate ways of modifying the code to send just the piece of information you want.
Yet another way to send mail is to use the SendMail 2.0 add-in utility created by Ron de Bruin. The SendMail 2.0 utility gives you the ability to send all or part of a workbook either in working format or with just the values of the current data and formulas. Once you install SendMail 2.0, to access these features, click Tools, and then click SendMail.
Before you use the e-mail features of Excel, either by feeding data to the Mail Merge Wizard or through the Microsoft Visual Basic® for Applications (VBA) code sample in this article, it is a good idea to ensure your data is structured so that there are no surprises. The following criteria are applicable for using the wizard but also improve predictability when using the code samples:
- Add column headers above each column in the first row such as Title, First Name, Last Name, Address1, and so forth.
- Ensure that individual pieces of information you want to work with are in separate fields. For example, separating the recipient's name into separate first and last name fields allows you to use just the parts you want for a specific task such as using the last name in a salutation and then combining the first and last fields in the address block in a letter.
- Ensure that each field name is unique to avoid ambiguity.
- Ensure each row of data refers to a single entity. For example, each row refers to one recipient.
- Avoid blank rows in your data.
Note The VBA code in the following sections was tested in Microsoft Outlook 2002 and Microsoft Outlook Express 6.0. It may or may not work with other e-mail clients.
The following subroutine sends the active workbook where the workbook that contains the code is not the active workbook:
Sub Mail_workbook()
ActiveWorkbook.SendMail "someone@microsoft.com","Subject_line"
End Sub
To e-mail the workbook that contains the code, then use the following line instead:
ThisWorkbook.SendMail "someone@microsoft.com","Subject_line"
**Note **The workbook doesn't have to be the active workbook in use at the time that the code is executed.
The following example illustrates how to send a single sheet in e-mail with the following options:
- By creating a workbook with just the active sheet
- By saving the workbook before sending it with a date/time stamp
- By sending the active workbook
- By deleting the file from your hard disk after you send it
Sub Mail_ActiveSheet()
Dim strDate As String
ActiveSheet.Copy
strDate = Format(Date, "dd-mm-yy") & " " & Format(Time, "h-mm-ss")
ActiveWorkbook.SaveAs "Part of " & ThisWorkbook.Name _
& " " & strDate & ".xls"
ActiveWorkbook.SendMail "someone@microsoft.com", _
"Subject_line"
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
ActiveWorkbook.Close False
End Sub
You can use the following line if you know which sheet you want to send:
...
Sheets("Sheet5").Copy
...
**Note **The code doesn't have to be in the active sheet when it is executed.
You can use the following sample code to send multiple worksheets in e-mail with the following options:
- By creating a workbook with two worksheets
- By saving the workbook before sending it with a date/time stamp
- By deleting the file from your hard disk after you send it
Sub Mail_SheetsArray()
Dim strDate As String
Sheets(Array("Sheet1", "Sheet3")).Copy
strDate = Format(Date, "dd-mm-yy") & " " & Format(Time, "h-mm-ss")
ActiveWorkbook.SaveAs "Part of " & ThisWorkbook.Name _
& " " & strDate & ".xls"
ActiveWorkbook.SendMail "someone@microsoft.com", _
"Subject_line"
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
ActiveWorkbook.Close False
End Sub
This subroutine sends a newly created workbook with just the visible cells in the selection. The cells are added as values using Paste Special in the workbook you send.
The routine saves the workbook before sending it by e-mail with a date/time stamp.
After the file is sent, the workbook is deleted from your hard disk.
- Because it sends only the visible cells, the subroutine also works if you want to send a range with hidden rows or columns in it.
The normal Copy and Paste commands make the hidden rows and columns visible!
Sub Mail_Selection()
Dim source As Range
Dim ColumnCount As Long
Dim FirstColumn As Long
Dim ColumnWidthArray() As Double
Dim lIndex As Long
Dim lCount As Long
Dim dest As Workbook
Dim i As Long
Dim strdate As String
Set source = Nothing
On Error Resume Next
Set source = Selection.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If source Is Nothing Then
MsgBox "The selection is not a range or the sheet is protect, please correct and try again.", vbOKOnly
Exit Sub
End If
If ActiveWindow.SelectedSheets.Count > 1 Or _
Selection.Cells.Count = 1 Or _
Selection.Areas.Count > 1 Then
MsgBox "An Error occurred :" & vbNewLine & vbNewLine & _
"You have more than one sheet selected." & vbNewLine & _
"You only selected one cell." & vbNewLine & _
"You selected more than one area." & vbNewLine & vbNewLine & _
"Please correct and try again.", vbOKOnly
Exit Sub
End If
Application.ScreenUpdating = False
ColumnCount = Selection.Columns.Count
FirstColumn = Selection.Cells(1).Column - 1
ReDim ColumnWidthArray(1 To ColumnCount)
lIndex = 0
For lCount = 1 To ColumnCount
If Columns(FirstColumn + lCount).Hidden = False Then
lIndex = lIndex + 1
ColumnWidthArray(lIndex) = Columns(FirstColumn + lCount).ColumnWidth
End If
Next lCount
Set dest = Workbooks.Add(xlWBATWorksheet)
source.Copy
With dest.Sheets(1)
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
For i = 1 To lIndex
.Columns(i).ColumnWidth = ColumnWidthArray(i)
Next
End With
strdate = Format(Now, "dd-mm-yy h-mm-ss")
With dest
.SaveAs "Selection of " & ThisWorkbook.Name _
& " " & strdate & ".xls"
.SendMail "ron@debruin.nl", _
"This is the Subject line"
.ChangeFileAccess xlReadOnly
Kill .FullName
.Close False
End With
Application.ScreenUpdating = True
End Sub
You can use this if you know the range you want to send:
Set source = Range("A1:E50").SpecialCells(xlCellTypeVisible)
Range("A1:E50").Select
Then you can remove this section:
If ActiveWindow.SelectedSheets.Count > 1 Or _
Selection.Cells.Count = 1 Or _
Selection.Areas.Count > 1 Then
MsgBox "An Error occurred :" & vbNewLine & vbNewLine & _
"You have more than one sheet selected." & vbNewLine & _
"You only selected one cell." & vbNewLine & _
"You selected more than one area." & vbNewLine & vbNewLine & _
"Please correct and try again.", vbOKOnly
Exit Sub
End If
This procedure illustrates how to send every worksheet with an address in cell A1 by e-mail. This way you can send each sheet to another person. It does this by cycling through each worksheet in the workbook and checking cell A1 for the @ character. If found, the code makes a copy of the worksheet and then sends the copy by e-mail to the address in cell A1. Finally, the code deletes the file copy from your hard disk.
Sub Mail_every_Worksheet()
Dim sh As Worksheet
Application.ScreenUpdating = False
For Each sh In ThisWorkbook.Worksheets
If sh.Range("a1").Value Like "*@*" Then
sh.Copy
ActiveWorkbook.SaveAs "Sheet " & sh.Name & " of " _
& ThisWorkbook.Name & ".xls"
ActiveWorkbook.SendMail ActiveSheet.Range("a1").Value, _
"Subject_line"
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
ActiveWorkbook.Close False
End If
Next sh
Application.ScreenUpdating = True
End Sub
To do this, add a sheet with the name mail to your workbook. Then, for every e-mail you want to send, create three columns that include:
- The sheet or sheets you want to send
- The e-mail address or addresses
- The subject of the e-mail
Columns A:C include the information for the first e-mail and D:F for the second one (see Figure 1). You can send 85 different e-mails this way (85*3 = 255 columns).
Figure 1. Send e-mail to multiple people
In this example, the following results:
- Ron and Dave receive sheet1, sheet3 and sheet5 (in one workbook) and the subject line of "Subject 1"
- Jelle receives sheet2 and sheet4 (in one workbook) and the subject line of "Subject 2"
The following code accomplishes this:
Sub Mail_sheets()
Dim MyArr As Variant
Dim last As Long
Dim shname As Long
Dim a As Integer
Dim Arr() As String
Dim N As Integer
Dim strdate As String
For a = 1 To 253 Step 3
If ThisWorkbook.Sheets("mail").Cells(1, a).Value = "" Then
Exit Sub
End
Application.ScreenUpdating = False
last = ThisWorkbook.Sheets("mail").Cells(Rows.Count, _
a).End(xlUp).Row
N = 0
For shname = 1 To last
N = N + 1
ReDim Preserve Arr(1 To N)
Arr(N) = ThisWorkbook.Sheets("mail").Cells(shname, a).Value
Next shname
ThisWorkbook.Sheets(Arr).Copy
strdate = Format(Date, "dd-mm-yy") & " " & _
Format(Time, "h-mm-ss")
ActiveWorkbook.SaveAs "Part of " & ThisWorkbook.Name _
& " " & strdate & ".xls"
With ThisWorkbook.Sheets("mail")
MyArr = .Range(.Cells(1, a + 1), .Cells(Rows.Count, _
a + 1).End(xlUp))
End With
ActiveWorkbook.SendMail MyArr, ThisWorkbook.Sheets("mail").Cells(1, a + 2).Value
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
ActiveWorkbook.Close False
Application.ScreenUpdating = True
Next a
End Sub
The preceding macros are just some examples you can use to send e-mail from Excel. The following examples show ways you can change the code to suit your needs.
Delete these lines to keep the file you sent:
...
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
...
Delete these four lines if you don't want to save the workbook:
...
strDate = Format(Date, "dd-mm-yy") & " " & Format(Time, "h-mm-ss")
ActiveWorkbook.SaveAs
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
...
Use a cell (A1) containing an e-mail address as follows:
...
ActiveWorkbook.SendMail Sheets("mysheet").Range("a1").Value, _
"Subject_line"
...
Use also a cell for the subject like this.
...
ActiveWorkbook.SendMail Sheets("mysheet").Range("a1").Value, _
Sheets("mysheet").Range("b1").Value
...
To send e-mail to more people use this line:
...
ActiveWorkbook.SendMail Array("someone@microsoft.com", "someone@microsoft.com"), _
"Subject_line"
...
To send e-mail to all addresses in a range:
...
Dim MyArr As Variant
MyArr = Sheets("mysheet").Range("c1:c10")
ActiveWorkbook.SendMail MyArr, _
"Subject_line"
...
If you use this line, you can choose an address in the address book or type one yourself and put some text in the body:
...
ActiveWorkbook.SendMail "", "Subject_line"
...
You can change the save line to this, for example:
...
ActiveWorkbook.SaveAs Sheets("mysheet").Range("d1").Value
ActiveWorkbook.SaveAs "myfilename"
...
Important Use error checking to verify that a file with that name doesn't already exist or isn't already open. In the examples above, the file name includes the date and time so that the chance the file name already exists is very small.
To paste cells as values you cannot protect the sheet. Alternatively, you can use unprotect and then protect the worksheet in the subroutine.
Use one of these lines to copy a single sheet:
...
Sh.copy
...
...
Activesheet.copy
...
Use this code to paste as values:
...
Cells.Copy
Cells.PasteSpecial xlPasteValues
Cells(1).Select
Application.CutCopyMode = False
...
If you copy more sheets in the newly created workbook then use this:
...
Worksheets.Select
Cells.Copy
Cells.PasteSpecial xlPasteValues
Cells(1).Select
Worksheets(1).Select
Application.CutCopyMode = False
...
The SendMail 2.0 utility is an add-in for sending customized Excel workbooks and worksheets by e-mail. In addition, SendMail allows significant customizing of what you send. As soon as you have the workbook open in Excel, you have the ability to send all or part of workbook either with the formatting or with just the values of the current data and formulas. Once you install SendMail 2.0, to access it, click Tools, and then click SendMail.
Note The SendMail 2.0 utility was tested in Outlook and Outlook Express. It will not work with other e-mail clients.
To install the Send Mail 2.0 utility for Excel 97 or later
Download and extract the SendMail utility to a local directory.
Copy SendMail 2.0.xla to the following directory:
local_drive:\Program Files\Microsoft Office\OfficeNumber\Library
**Note **Depending on the version of Excel, the OfficeNumber directory may be only Office or may include a number. For example:
local_drive:\Program Files\Microsoft Office\Office\Library
-OR-
local_drive:\Program Files\Microsoft Office\Office11\Library
Open Excel.
Note You must have a workbook open.
Click the Tools menu and then click Add-ins.
Click Browse. . . to browse to local_drive:\Program Files\Microsoft Office\Officenumber\Library.
Click SendMail 2.0.xla and then click Open
Verify SendMail 2.0 is checked and then click OK.
For instructions on using SendMail 2.0, see the User Guide included in the download.
In this article, we looked at several code samples you can use to make mailing from Excel much easier. We also introduced the SendMail add-in that you can use to assist you in sending customized Excel workbooks and worksheets by e-mail. Exploring and implementing these tools in your own applications can help make your job as a developer much easier and make your solutions more versatile.
Ron de Bruin is an Excel Most Valuable Professional (MVP) and a frequent contributor to the newsgroups. For more information, see http://www.rondebruin.nl.
Frank C. Rice is a Microsoft employee and frequent contributor to the Office Developer Center.