Hands Off That Email Attachment!
April 14, 2008 – 5:49 pm by JP
About halfway down the Outlook page, there is some VBA code for opening an Excel workbook attached to an email, running a macro on it, then cleaning up and moving the email to another folder.
Here is some more sample code to make your macro even more intelligent. This code opens the attachment, then scans through the spreadsheet looking for an error condition. If the error condition is met, an email is generated to another mailbox, as an alert, and the email is left in the Inbox to be looked at by a human. If the error condition isn’t met, there’s no reason to look at the email, so it gets marked as read and moved to an archive folder.
If you are like me, then your time is valuable. You don’t want to spend time looking at emails that you don’t need to work on. This code lets me focus on high-value activities while using Outlook’s built-in capabilities to ignore the spreadsheets that don’t need personal attention.
First you want to open ThisOutlookSession and paste this event code:
1 2 | Private WithEvents QueueInbox As Outlook.Items Dim bWasPosted As Boolean |
Really you can use anything in place of “QueueInbox”, but I use something that will relate to the task so I can easily identify what the code is doing. The boolean variable is put in the global section because we are using it in one procedure (the mail sending sub) and checking the value in another sub.
Now you need to tell Outlook to monitor your chosen Inbox for new items. This code placed in the Application_Startup event will do that.
1 | Set QueueInbox = objNS.Folders("Mailbox - My Mailbox Name").Folders("Inbox").Items |
Replace “My Mailbox Name” with the name of the mailbox you want to check. For example, if I were running this on my own Inbox, the code would be
1 | Set QueueInbox = objNS.Folders("Mailbox - Jimmy Pena").Folders("Inbox").Items |
If you don’t have an Application_Startup event, just put “Private Sub Application_Startup()” right above the Set statement, and “End Sub” right below it.
Now on to the real work. When a new item is added to the Inbox we selected, it saves and opens the attachment, checks to make sure everything is OK, and if so, moves the email to an archive folder. Don’t forget to set a reference to the Excel object library (see binding page for assistance).
Of course I make some assumptions here, which you might want to change. For example, the emails we are checking have a known sender and subject, which was pre-arranged. Also, they always have one .xls attachment. If you can agree on a system like this, you’ll be able to use Outlook code to automate some pretty boring processes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | Private Sub QueueInbox_ItemAdd(ByVal Item As Object)
Dim objNS As Outlook.NameSpace
Dim ArchiveFolder As Outlook.MAPIFolder
Dim Msg As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
Const attPath As String = “C:\”
Dim colACount As Long
Dim colGCount As Long
Dim cell As Excel.Range
Dim MyBook As Excel.Workbook
Dim MySheet As Excel.Worksheet
Dim colARange As Excel.Range
Dim colGRange As Excel.Range
Dim bBadCount As Boolean
bWasPosted = False
bBadCount = False
Set objNS = GetNamespace(”MAPI”)
' the archive folder we are moving emails to
Set ArchiveFolder = objNS.Folders(”Mailbox - My Mailbox Name”)._
Folders(”Inbox”).Folders(”Archive”)
' check to make sure we are looking at a mailitem
If TypeOf Item Is Outlook.MailItem Then
If (Item.SenderName = “MySender@somewhere.com”) And _
(Item.Subject = “Attachment You Requested”) Then
' obj ref to msg
Set Msg = Item
' get attachment
Set myAttachments = Msg.Attachments
Att = myAttachments.Item(1).DisplayName
myAttachments.Item(1).SaveAsFile attPath & Att
' open workbook and check for errors
Set XLApp = New Excel.Application
Set MyBook = XLApp.Workbooks.Open(attPath & Att)
Set MySheet = MyBook.Sheets(1)
' check count of columns A & G to make sure they match
' at this point you could do anything you want to the workbook, as if you
' were in the Excel VBE
Set colARange = MySheet.Range(”A2:A5000″)
Set colGRange = MySheet.Range(”G2:G5000″)
colACount = colARange.SpecialCells(xlCellTypeConstants).Count
colGCount = colGRange.SpecialCells(xlCellTypeConstants).Count
If colACount <> colGCount Then
' we found an error!
MyBook.Close False
' call other macro and pass email to it as an argument,
' so we can use some properties of the current mailitem
Call PostMsg(Msg)
bBadCount = True
End If
' bBadCount is a boolean variable checking if the match count
' caused an error, we skip further checks if that is the case
' because we only need one error
If bBadCount = False Then
' the count matched, but maybe we have invalid values
For Each cell In colGRange.SpecialCells(xlCellTypeConstants, 2)
If (cell.Value = “#N/A”) Then
MyBook.Close False
Call PostMsg(Msg)
End If
Next cell
End If
' at this point, if PostMsg was called,
' bWasPosted would be True
If bWasPosted = False Then
' we didn’t post a msg to MyInbox, so there must be
' nothing wrong with the attachment, so we can move it
With Msg
.UnRead = False
.Move ArchiveFolder
End With
End If
End If
End If
ExitProc:
On Error Resume Next
XLApp.DisplayAlerts = False
XLApp.Workbooks.Close
XLApp.DisplayAlerts = True
Kill attPath & Att
XLApp.Quit
On Error GoTo 0
Set ArchiveFolder = Nothing
Set objNS = Nothing
End Sub |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Sub PostMsg(Msg As Outlook.MailItem) ' ' sub that actually puts the email in the inbox ' Dim NotifyMsg As Outlook.MailItem Dim MyFolder As Outlook.MAPIFolder Dim objNS As Outlook.NameSpace Dim strMsg As String Set objNS = GetNamespace(”MAPI”) Set MyFolder = objNS.Folders(”Mailbox - Jimmy Pena”).Folders(”Inbox”) Set NotifyMsg = MyFolder.Items.Add(olMailItem) With NotifyMsg .Subject = “Invalid Attachment Received” .Importance = olImportanceHigh .To = “jpena@myemail.com” strMsg = “The following message was received by Queue Inbox on ” & Msg.ReceivedTime & “:” strMsg = strMsg & vbCr & vbCr & Msg.Body strMsg = strMsg & vbCr & vbCr & “This is an automatically generated message.” .Body = strMsg .UnRead = True End With bWasPosted = True NotifyMsg.Send End Sub |
After implementing this code, you’ll see that it checks incoming mail items for the ones with the appropriate sender and subject, browses through the attachment for errors, and sends an email to your Inbox of choice if an error is found. If no error is found, it quietly marks the email as read and moves it to another folder.
Now, hands off!
Enjoy,
JP
Print This Post
|
Email This Post
|
Permalink
|
Filed Under: Excel, Outlook, VBA, automation
Tags: attachments, automation, Excel, Outlook, VBA
This post has 121 views since April 14, 2008 – 5:49 pm.
























