Add, save, and open Outlook-item attachments
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:
fso.DeleteFile strFileName
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.
Fantastic Article. I just needed a little help with VBA inside Outlook. (Never mind the WSH and fso which confused me.) This article helped me do everything I needed to do = Open Multiple Excel Attachments in Outlook, and they must be done within the same instance of Excel (something which "Call Shell" did not do).
Now I can write an Excel Macro to move the sepearate files from the Window menu into separate worksheets in a single workbook.
Thanks. Very Very Good Article
Easy to understand simple task require simple code and sometimes it's not easy to find! Thanks
i wud like to know about working with .msg type attachments.
i know there is a mailto command that allows you to attach a file - is there a similar command that allows you to detach?
basically what i want to do is send a file attachment to someone and then give them the option of automatically forwarding the email but without any of the original text but just the attachment
Outlook application opens and I am able to send an attachment, however I am unable to add more than one line to the body (text of the msg)
regards
Very useful document but with one question i have a macro to create a task from an email which copies the email but not the attachments. Is there any way to do this?
gaurav, you didn't say what you wanted to do with the .msg attachments. If you want to create a copy, try the Namespace.GetItemFromTemplate method, which can take an .msg file path as an argument. Or, check out the Import method available in the Redemption library from http://www.dimastr.com/redemption/
Peter, see http://www.outlookcode.com/d/code/copyatts.htm for code that shows how to copy attachments.
laxmi, you can add as much text as you want to a message.
Check out this great tutorial on using Microsoft Outlook for managing your ebay & amazon sales, or use it as an Outlook programming quickstart:
http://www.321books.co.uk/ebooks/outlook-vba-tutorial.htm
I am trying to strip out and save an attachment. The attachment is an excel file which is itself within an attached .msg file. I set up a routine to firstly save the .msg file to temp folder. I then need to open it and strip out and save attached excel file. However WshShell.Run will not open files of type .msg. ShellExecute will, but the shell command is asynchronous - the macro will not wait for the file to open before trying to save the attachment - big problem! How do you force the macro to wait or the shell command to be synchronous, or is there any other way to achieve this?
great article, sue!
i have one question - i receive emails that have been forwarded like a milion times (jokes mostly). The goal is to keep opening attachments which are messages until there are no more. the last message opened may have picture attachments or none (only body). Is the only way to savefile and then open the attachment using S***** and keep doing so? is there no "doublelick" method akin to double clicking the attched message within the mailitem?
Regards,
aveesh***ar
The set objAtt line forces a run-time 424 error 'object required'. The author does not address this or any other setup requirements that would prevent this - making the code useless. The article is either incomplete or contains errors.
i am trying to attach jpg files, but can't. It used to work earlier before i updated Outlook.
I extract the path of the jpg files from hyperlinks in my access database. could that be the problem. It attaches other .txt files.
please help