Many common Outlook operations center on attachments—adding them to messages and other items, opening them, and saving them as system files. Let’s explore how Outlook programmers work with attachments and look at the Scripting Runtime programming library, which comes in handy when working with file attachments.
Adding an Attachment
Every Outlook item, except the yellow-sticky-note NoteItem object, supports an Attachments collection. Like other collections, the Attachments collection supports an Add method to attach a new file, an Item method to help enumerate the attachments in the collection, and a Remove method to delete an attachment from the item. However, the Remove method doesn’t work in all versions of Outlook, so I recommend avoiding it.
When you attach a file to an Outlook item, you must provide either the path to a file on your system or an Outlook item object, such as a ContactItem or MailItem. Other parameters are optional. Unfortunately, the Help file for Outlook 2002 displays the details of the AddressEntries.Add method instead of the Attachments.Add method. You can find information about Attachments.Add at http://support.microsoft.com/support/office/inprodhlp/outlook/olmthaddattachmentsobj.asp, but this Web page doesn’t tell the whole story.
The basic syntax for adding a file as an attachment to a new Outlook message looks like this:
Set objOL = _ CreateObject("Outlook.Application") Set objMsg = _ objOL.CreateItem(olMailItem) Set objAttachments = _ objMsg.Attachments Set objAtt = _ objAttachments.Add("c:\myfile.doc")
To attach a different file, just change the value for the required Source property from "c:\myfile.doc" to the full path for the file that you want to attach.
To add a shortcut to a file rather than adding the actual file, add a value for the optional Type property, as in
Set objAtt = _ objAttachments.Add("c:\myfile.doc", _ olByReference)
Note, however, that attaching a file with Type = olByReference creates a .lnk file attachment, and the Outlook Email Security Update blocks .lnk files. In other words, users won’t be able to use the shortcut. A more universal method is to use the file:// protocol to add a hyperlink to the text of the message, as in
objMsg.Body = objMsg.Body & _ vbCrLf & vbCrLf & _ "<file://c:\myfile.doc>"
This method also has drawbacks. In Outlook 2000 and earlier versions, setting MailItem’s Body property forces the message to Rich Text Format (RTF). You might prefer to build an HTML-formatted message instead (so that non-Outlook recipients can handle it) and include in the MailItem HTMLBody property string an <a></a> tag to create a link to the file.
In addition to supporting the Source and Type properties, the Attachment object also supports optional Position and DisplayName properties that you can change after you create the attachment:
With objAtt .Position = 0 .DisplayName = "MyFile.doc" End With
If the Outlook item is in RTF format, Position controls where the attachment appears. If the item is in HTML or plain text format, Outlook ignores the value for Position and displays the attachment in a separate box below the message header.
The Scripting Runtime Library
Now that you know how to add attachments to Outlook items, you’re probably wondering how to save them as files and open them from messages that you receive or from other Outlook items. These tasks are easier to accomplish with the aid of Scripting Runtime, a programming library that’s part of Windows Script Host (WSH). Scripting Runtime is available on Windows 98 or later systems and as part of Microsoft Windows Script 5.6, which you can download from http://msdn.microsoft.com/downloads/sample.asp?url=/msdn-files/027/001/733/msdncompositedoc.xml. You’ll need to add a reference to Scripting Runtime (c:\windows\system32\scrrun.dll) to your VBA project. Scripting Runtime documentation is available at http://msdn.microsoft.com/library/en-us/script56/html/fsooriscriptingrun-timereference.asp.
The basic component of Scripting Runtime is FileSystemObject, which provides methods to access files and folders. Let’s say you want to save an Outlook message attachment as a file. First, check whether a file already exists with the name you want to use. FileSystemObject provides a FileExists method to give you that information. The code
Dim fso As New Scripting.FileSystemObject Set objAtt = objMsg.Attachments(1) strFileName = "C:\Temp\" & objAtt.FileName If Not fso.FileExists(strFileName) Then objAtt.SaveAsFile strFileName End If
saves the first attachment in a MailItem object (i.e., Outlook message) named objMsg only if the desired file name doesn’t already exist. If you later want to delete the saved file, you can use the FileSystemObject’s simple DeleteFile method:
FileSystemObject doesn’t have a method for opening an attached file directly from inside a message. When a user double-clicks an Outlook-item attachment to open it, Outlook saves a temporary copy of the file to the user’s system, then opens that copy. If you want to open attachments programmatically, you need to do the same thing—save a copy locally, then open the saved file.
You’ve already seen how to use the SaveAsFile method to save a message attachment as a file. To open it, you use another feature of WSH that lets you write a procedure that works similarly to double-clicking a file. When you double-click a file, Windows checks the file extension (e.g., .doc, .exe) to see what program to use to open the file. An .exe file is a program, so Windows just runs it. A .doc file is a Microsoft Word document, so Windows runs Word and opens the .doc file in Word.
WSH includes a Shell object that supports a Run method that can run any file without your specifying the program with which the file is associated. Listing 1 shows a RunFile subroutine that you can call from other procedures to open any file on your system. Note the error-handling code that deals with cases in which the file has no associated program.
Opening File Attachments
Now, we can put some of these techniques together into a useful macro that opens all the attachments in the message you’ve selected in a folder. The OpenAllFiles subroutine in Listing 2 loops through all the attachments in the item, saving each to a local folder, then calling the RunFile subroutine in Listing 1 to open the file. Note that OpenAllFiles doesn’t check first to see whether a file by the same name exists.
I’ve just scratched the surface of working with Outlook-item attachments, but you now know how to attach a file or Outlook item programmatically and how to save attached files and open those saved files. You’ve also learned about WSH and its FileSystemObject, which can help you work with files and folders in your Outlook VBA macros.