using vba to manage your outlook email attachments

Upload: asur100

Post on 14-Apr-2018

230 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    1/17

    Using VBA to Manage Your Outlook Email Attachments

    Some people get a lot of email attachments! This tutorial came about as aresult of an enquiry from a client of mine who received each day aroundtwenty emails, each with an attached file. She had to open each emailthen save each file to disk before working on the data they contained. Itwas a tedious process and she asked me if it was possible to automate it. Isaid yes before realising that I hadn't ever done any Outlookprogramming! But I was glad to discover that Outlook is as easy toprogram with VBA as the rest of the Microsoft Office family.

    This tutorial shows you how to create an Outlook macro which scans yourInbox for messages that contain attachments, then saves them to anamed folder. The next tutorial in the series takes the technique a stepfurther and illustrates how you can create a similar macro in Excel toimport newly arrived data straight into an Excel workbook.

    About Outlook Macros

    Writing VBA code in Microsoft Outlook is no different from working in yourother Microsoft Office programs. Outlook 2000 and 2002 have the familiarVisual Basic Editor with all the same tools you are used to. Outlook 97does not have a Visual Basic Editor, instead using VBScript attached tocustom forms for its macros. But this doesn't mean that this project isn'tsuitable for Outlook 97 users. You can program Outlook 97 using VBAAutomation from one of the other Office programs. Only a fewmodifications to the code are required and a full explanation of how to do

    this is given at the end of this tutorial. Outlook 97 users might want toread through this section first .

    Unlike other Microsoft Office programs, Outlook can support only one VBAProject at a time. This makes sense really, as you open only one instanceof Outlook at a time unlike for example Word or Excel in which each opendocument or workbook can host its own VBA Project.

    There is no simple way to distribute Outlook VBA code to users other than

    exporting VBA modules and relying on the user to import them into theVBA Project in their own copy of Outlook. Outlook VBA code can be

    1

    http://www.fontstuff.com/outlook/oltut01.htm#outlook97%23outlook97http://www.fontstuff.com/outlook/oltut01.htm#outlook97%23outlook97
  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    2/17

    distributed using COM Add-ins but this is beyond the scope of this tutorial.But this need not be a problem if you are creating Outlook macros for yourown use, or if you are able to import code modules into other people'scopies of the program (or can trust them to do it themselves!).

    A Macro to Collect Email Attachments

    Start Outlook 2000 or 2002 and open the Visual Basic Editor ( Tools >Macro > Visual Basic Editor or Keys: Alt+F11 ). The Project Explorerwindow displays the current (and only) project. Add a new code module bychoosing Insert > Module and give it a suitable name by entering it intothe Name section of the Properties window. I have chosen to call mymodule GetEmailAttachments .

    >>>

    The module's code window should open automatically. If it doesn't, open itby double-clicking the module name in the Project Explorer window. You're

    now ready to build the code for the macro...

    Name the Macro, Add an Error Handler and Declare theVariables

    Enter a suitable name for your macro. I've chosen to call itGetAttachments

    Sub GetAttachments()

    End Sub

    It's good practice to add an error handling routine to all your macros, justin case something goes wrong, and the statement that tells the macrowhere to find it should always come at the top of your code:

    On Error GoTo GetAttachments_err

    This line tells the macro to jump to a label (like a bookmark in your code)

    called GetAttachments_err that it will find at the end of the procedure

    2

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    3/17

    (we'll create it later). Next, declare the variables we are going to use in themacro:

    Dim ns As NameSpace

    Dim Inbox As MAPIFolderDim Item As Object

    Dim Atmt As Attachment

    Dim FileName As String

    Dim i As Integer

    If you haven't programmed Outlook before some terms here will beunfamiliar. I'll explain what these variables are going to be used for...

    The NameSpace is the object that gives you access to all Outlook'sfolders. In Outlook there is only one and it is called "MAPI" which is anacronym for Messaging Application Programming Interface .

    We are going to be referring to a mail folder (a MAPIFolder object )which we have given the name Inbox but the macro won't know whichactual folder that is until we tell it by giving the variable a value in thenext step.

    We will be using Atmt to refer to the attachment objects we arelooking for.

    The FileName variable is a text string that will be used to create aname and save path for each attachment as it is saved.

    The integer variable i will be used as a counter to log the progress of the macro.

    Set the Values of Variables

    Some of the variables need to have their values set at the start of themacro:

    Set ns = GetNamespace("MAPI")

    Set Inbox = ns.GetDefaultFolder(olFolderInbox)

    i = 0

    Note that when you are setting the value of the Inbox variable the VisualBasic Editor provides a list of all the possible default folders. This gives anindication of the possibilities when programming Outlook. Here, you needto choose olFolderInbox from the list.

    3

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    4/17

    Search the Folder for Attachments

    First of all, we need an If Statement to check that there are messages inthe Inbox folder, and abandon the search if there are none. The first line of the If Statement counts the number of items in the folder:

    If Inbox.Items.Count = 0 Then

    MsgBox "There are no messages in the Inbox.", vbInformation, _

    "Nothing Found"

    Exit Sub

    End If

    If there are no message in the Inbox folder the macro displays a messageto the user and then exits (i.e. terminates). If, however, there aremessages in the Inbox folder the macro proceeds to examine each forattachments. This is done using a pair of nested loops (i.e. one looprunning inside the other:

    For Each Item In Inbox.Items

    For Each Atmt In Item.AttachmentsFileName = "C:\Email Attachments\" & Atmt.FileName

    Atmt.SaveAsFile FileName

    i = i + 1

    Next Atmt

    Next Item

    The outer loop ( For Each Item... Next Item ) looks at each Item in the Inbox folder in turn. Although the Item variable was declared as an Object it

    refers to mail messages, which are by definition the only objects that the

    4

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    5/17

    Inbox folder contains because it is a mail folder. The outer loop runs for asmany times as there are mail messages in the folder.

    Each time the outer loop encounters a mail message the inner loop ( For

    Each Atmt... Next Atmt ) runs for as many times as there are files attachedto the mail message. If there are no attached files the macro continueswith to the outer loop.

    If the inner loop finds an attached file it constructs a text string (theFileName variable) representing the save path of the file. The save pathconsists of the full path to the folder in which the attachments are to besaved, plus the actual filename of the attachment.

    Note that I have "hard coded" the folder path. I could haveadded some code to allow the user to choose a folder to savethe attachments in (but I'm trying to keep things simple!). If you hard code a folder path like this you must make sure thatthe folder exists before you run the macro. The code will notcreate it for you.

    The inner lop then saves the attachment to the chosen folder andincrements the counter variable ( i) by one. This counter will be used laterto notify the user how many attachments were found.

    Display a Summary Message

    After the loops have examined all the mail messages, the only job thatremains is to notify the user of the results. I have been countingattachments using the variable i. The value it now holds represents thenumber of attachments that were found and saved. I am using an If Statement to display a message to the user:

    If i > 0 Then

    MsgBox "I found " & i & " attached files." _

    & vbCrLf & "I have saved them into the C:\Email Attachments

    folder." _

    & vbCrLf & vbCrLf & "Have a nice day.", vbInformation,

    "Finished!"

    Else

    MsgBox "I didn't find any attached files in your mail.",vbInformation, _

    5

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    6/17

    "Finished!"

    End If

    If i is greater than zero then attachments were found and saved so the

    message tells the user how many (again using the value of i) and wherethey were saved to.

    If i is not greater than zero (i.e. it must be zero) then the user is notifiedthat no attachments were found.

    Clear the Memory

    The main work of the macro has been done. There a couple of housekeeping tasks to perform. The first task is to clear the computer's

    memory by setting the value of any object variables (i.e. variable whosevalues are assigned using the keyword Set ) to "Nothing":

    GetAttachments_exit:

    Set Atmt = Nothing

    Set Item = Nothing

    Set ns = Nothing

    Exit Sub

    The first line of this code is a label. It will be used by the error handlingprocedure (coming next). In VBA labels are always followed by a colon andare not regarded as executable code, merely a kind of "bookmark".

    After each of the object variables are set to "Nothing" the line Exit Sub tells the macro that if it reaches this point it can finish. The reason it ishere is that this is not the last line of code in the procedure. Next comes

    the Error Handler and it is necessary to terminate the macro before theError Handler (unless, of course, there is an error!).

    Handle Errors

    I have included a basic "all purpose" error handler here. Remember that atthe beginning of the macro code I put the statement: On Error GoToGetAttachments_err . That statement gave the instruction that, in theevent of an error, the macro should jump down to the label

    GetAttachments_err and continue from there. Here is what is finds:

    6

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    7/17

    GetAttachments_err:

    MsgBox "An unexpected error has occurred." _

    & vbCrLf & "Please note and report the following information."

    _

    & vbCrLf & "Macro Name: GetAttachments" _

    & vbCrLf & "Error Number: " & Err.Number _

    & vbCrLf & "Error Description: " & Err.Description _

    , vbCritical, "Error!"

    Resume GetAttachments_exit

    In this case my error handler consists simply of a message notifying theuser of the details of the error. This is followed by the statement: ResumeGetAttachments_exit which tells the macro to jump up to the labelGetAttachments_exit and continue from there. This makes sure that anyloose ends are tied up before the macro terminates.

    The reason for including an error handler is that this gives the developerthe opportunity to deals with errors in an appropriate way. If, for example,I knew that a specific error was likely to occur if the user had forgotten todo something important before running the macro, I could include code inmy error handler to deal with it in an appropriate way.

    If you don't include an error handler, the user sees the standard VBA errormessage:

    This message is intended for the eyes of the VBA developer. The averageuser has no idea what it means and will probably press the Debug buttonbecause that is the highlighted one and to most users that means "PressMe!". Of course that is exactly what they should not do because it takes

    them into the Visual Basic Editor window with their macro in break mode.

    7

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    8/17

    The only safe thing for the user to do is press the End button, which willterminate the macro - but, of course, they don't know that!

    But with an error handler in place you can take charge and display your

    own message instead:

    The error handler code safely shuts down the macro without panicking theuser and, all being well, without causing any harm!

    At last we can end the procedure with the line:

    Exit Sub

    Test and Save the Macro

    Before running the macro you should check it for obvious errors and savethe code module. Choose to Debug > Compile Projectname to compilethe code and check for any coding errors that were not apparent when youtyped the code. Then save File > Save VbaProject.OTM to save thechanges you have made to Outlook's code:

    >>>

    Running the Macro

    Macros in Outlook can be run in the same way as you would run a macroin any other Microsoft Office program. From the Outlook main windowchoose Tools > Macro > Macros to display the Macros dialog, select

    your macro, and click Run ...

    8

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    9/17

    Alternatively you can create a custom toolbar button or menu item andassign the macro to it.

    When the macro finishes it displays a message detailing how manyattachments were found and where the were saved:

    Or, if no attachments were found:

    If the Inbox folder is empty this message will be displayed:

    Important Notes When this macro saves attached files, any files already in the target

    folder with the same filenames as the new files will be overwrittenwithout warning. See the note in Additional Refinements below on how

    to include a datestamp in the filename.

    9

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    10/17

    Remember to create the target folder before running the macro. If the save path is incorrect, misspelled or doesn't exist the macro willreturn an error (although no harm will be done).

    Additional RefinementsI wanted to keep this tutorial as simple as possible, so it only makes use of a fraction of the VBA programming power that can be used in Outlook.Future tutorials will explore other areas, but here are some refinementsthat can be added to the macro to make it more powerful...

    Save Only Specific File Types

    You may want to save only files of a specific type, such as Excelworkbooks or Word documents. A simple If Statement can check the fileextension and only save files that have, for example, an extension endingin xls (for Excel workbooks). The additions are marked in red :

    For Each Item In Inbox.Items

    For Each Atmt In Item.Attachments

    If Right(Atmt.FileName, 3) = "xls" Then

    FileName = "C:\Email Attachments\" & Atmt.FileName

    Atmt.SaveAsFile FileNamei = i + 1

    End If

    Next Atmt

    Next Item

    Look in a Named Subfolder

    If you are in the habit of filing your mail messages into subfolders, perhapsdoing this automatically by setting up a rule for incoming mail, you mightwant to scan a specific subfolder of the Inbox rather than the Inbox folderitself. This example will cause the macro to search in a folder called SalesReports which is located inside the main Inbox folder. It requires anadditional variable declaration at the top of the macro's code:

    Dim SubFolder As MAPIFolder

    Another line sets the value of the SubFolder variable (this line must comeafter the line that sets the value of the Inbox variable):

    10

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    11/17

    Set SubFolder = Inbox.Folders("Sales Reports")

    The code which scans for messages and attachments also needs to bemodified by substituting the variable name SubFolder for the original

    variable name Inbox . The message text has been modified too. Thechanges and additions are marked in red :

    If SubFolder .Items.Count = 0 Then

    MsgBox "There are no messages in the Sales Reports folder ." _

    , vbInformation, "Nothing Found"

    Exit Sub

    End If

    If SubFolder .Items.Count > 0 Then

    For Each Item In SubFolder.Items

    For Each Atmt In Item.Attachments

    FileName = "C:\Email Attachments\" & Atmt.FileName

    Atmt.SaveAsFile FileName

    i = i + 1

    Next Atmt

    Next Item

    End If

    Datestamp the Saved Files

    The SaveAsFile method used to save an attachment will overwrite anexisting file of the same name without warning. This might cause youproblems! Suppose each day you received attached files that had thesame name, and you ran the macro before you had dealt with yesterday'sfiles? Or what if you hadn't run the macro for a couple of days and you hadseveral mail messages, each containing different files but with the same

    filename?

    The answer would be to give each saved file some sort of unique identifierthat would set it apart from the others. There are several ways you can dothis, each making use of the various properties of a mail item that you canretrieve using VBA. You could append some of this information to thefilename to make it unique. You have lots of choices, and all you have todo is modify the line of code that generates the filename with which theattachment is saved - here are some suggestions...

    11

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    12/17

    EntryID

    The EntryID property of an Outlook mail item is a unique 48 characteralphanumeric string assigned to the item when it arrives. It looks

    something like this:

    0000000080907036605CA742B72580C92B48995C64785300

    Your code line would be (additions are marked in red ):

    FileName = "C:\Email Attachments\" & Item.EntryID & Atmt.FileName

    As you can see, unless you choose to add just part of this string you endup with rather long filenames...

    CreationTime

    In fact there are three date/time properties that apply to each mail item,

    CreationTime , SentOn and ReceivedTime . Of these CreationTime is mostlikely to be unique, being the time at which the sender created the mailmessage to which the attachments belonged. All these properties aresupplied as in the form of a full date and time stamp in the formatmm/dd/yyyy hh:nn:ss . This is read by the code in this format completewith slashes and colons so needs formatting before it is incorporated intothe filename. An example would be (additions are marked in red ):

    FileName = "C:\Email Attachments\" & _

    Format(Item.CreationTime, "yyyymmdd_hhnnss_") & Atmt.FileName

    Which would result in filenames sensibly timestamped and looking likethis...

    12

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    13/17

    Show the User the Saved Files

    You might like to offer the user the opportunity to view the saved files inWindows Explorer . This involves modifying the message near the end of

    the macro to include a question asking if the user wants to do this, andmaking use of the VBA Shell command to open the Windows Explorer program. First of all you need to add a variable declaration to those at thetop of the macro code:

    Dim varResponse As VbMsgBoxResult

    NOTE: Office 97 does not have the VBA constantvbMessageBoxResult so if you are working with Office 97 use

    Variant instead.

    This variable will hold the user's response when they click the Yes or No button on the modified message box. The modified code looks like this:

    If i > 0 Then

    varResponse = MsgBox("I found " & i & " attached files." _

    & vbCrLf & "I have saved them into the C:\Email Attachments

    folder." _

    & vbCrLf & vbCrLf & "Would you like to view the files now?" _, vbQuestion + vbYesNo, "Finished!")

    If varResponse = vbYes Then

    Shell "Explorer.exe /e,C:\Email Attachments", vbNormalFocus

    End If

    Else

    MsgBox "I didn't find any attached files in your mail.",

    vbInformation, _

    "Finished!"

    End If

    The message box code has been modified to display Yes and No buttons tothe message box, as well as vbQuestion icon. An If Statement analyses theuser's response and it is Yes it runs the line of code that opens WindowsExplorer displaying the appropriate folder. The new message box looks likethis...

    13

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    14/17

    Programming Outlook 97

    Outlook 97 doesn't have the VBA Editor that accompanies the other Office97 programs. This means that you can't program Outlook 97 from withinOutlook itself. But Outlook 97 has a VBA object model and, thanks to VBAAutomation (the process by which different programs talk to each other

    through VBA), you can create a macro in Excel, Access or Word that usesthe same code as described in this tutorial. A few small modifications arerequired:

    Set a Reference to the Outlook Object Model

    Although this is primarily intended for users of Office 97, the same methodcan be applied to Office 2000 and Office 2002 if you want to run the macrofrom within another program.

    Excel 97 or Word 97: Open the Visual Basic Editor in your chosenprogram and in the Project Explorer select the name of the file in whichyou want to create your macro (you might choose to use Personal.xls inExcel 97 or Normal.dot in Word 97). If necessary, add a code module asdescribed above.

    Access 97: This version of Access does not have the same Visual BasicEditor as the other programs but everything else works the same way.

    Instead, click the Modules tab of the Access database window. If you wantto place your code in an existing module, double-click it to open it.Otherwise click the New button to open a new code module (remember tosave it when prompted).

    All Programs: Choose Tools > References to open the References dialog. Scroll down the list until you find Microsoft Outlook 8.0 ObjectModel and place a tick in the box next to it. Click the OK button. [Click thethumbnail below to see a full-sized image):

    14

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    15/17

    Setting a reference to the Outlook object model gives the current VBAProject access to Outlook's VBA library so that it understands and cancheck and execute your Outlook programming commands.

    Add Commands to Communicate with Outlook

    Enter an additional variable declaration at the beginning of the macrocode to open a connection with Outlook:

    Dim appOl As New Outlook.Application

    Those variables which refer specifically to Outlook objects must now beedited so that the macro knows you are speaking to Outlook and not thehost program:

    Dim ns As Outlook.NameSpace

    Dim Inbox As Outlook.MAPIFolder

    Dim Atmt As Outlook.Attachment

    The code assigning a value to the namespace variable needs to bemodified:

    Set ns = appOl.GetNamespace("MAPI")

    Finally, an additional statement is required when clearing the memory:

    Set appOl = Nothing

    You can download a code module containing the entire macro code forOutlook 97 below.

    About Outlook Security

    Because of concerns about macro security, specifically from email viruses,various obstacles are put in the way of Outlook programmers. The macrosdescribed here will pose no threat to the security of your Outlook data andcan be run on Outlook 97 with no further action. Outlook 2000 and 2002however are equipped with various tools to monitor macro security.

    15

    http://www.fontstuff.com/images/oltut01q.gif
  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    16/17

    Depending on your existing security settings, you may find that when youtry and run your macro you see the following message:

    You need to change the security settings to permit VBA code to be run.Choose Tools > Macro > Security to display the Security dialog. Setthe security level to Medium and click OK .

    After you do this, the first time in an Outlook session that you try to run amacro or open the Visual Basic Editor you see a warning message seekingyour permission to run macros:

    Choose Enable Macros to proceed. It is very unwise to set the securitysetting to Low !

    Download the Code

    16

  • 7/27/2019 Using VBA to Manage Your Outlook Email Attachments

    17/17

    You can download a text file that can be imported into your host programas a ready-made code module. Each file contains two macros. One is thebasic GetAttachments macro built in this tutorial. The other, namedSaveAttachmentsToFolder contains examples of the enhancementsdescribed in the Additional Refinements section above.

    Click on one of the links below and save the file to disk. Your browser willprobably warn you about the potential dangers of downloading filescontaining code (a wise precaution!). To install either code module, openthe Visual Basic Editor and select VB Project into which you want to importthe code. Choose File > Import (or right-click and choose Import ) andlocate and select the .bas file then click OK . A new module will be created.

    17