In Outlook programming : Looping individual mails inside the Inbox, blogger Deva Gnanam .J shows some sample code for looping through the default Inbox and performing some action on the emails in that folder.
The purpose of this post is to examine that code and explain why I think it needs improvement.
First, here is the unedited code from that post.
'myLoop method
Sub myLoop()
'Declaration
Dim olApp As Outlook.Application
Dim olNs As Outlook.NameSpace
Dim olFldr As Outlook.MAPIFolder
Dim olItms As Outlook.Items
Dim olMail As Object
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set olFldr = olNs.GetDefaultFolder(olFolderInbox)
Set olItms = olFldr.Items
'Loop the items
For Each olMail In olItms
'Here you need to use olMail Object to inspect individual mails inside the Inbox
Next olMail
'Release the objects appropriately
Set olFldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
I'm going to point out two things with the above code that need fixing:
- When you are writing native VBA code for an Office Application (i.e. Outlook VBA code to be used inside Outlook), never use the New keyword with the Application Object.
- If you are looping through items a folder, remember that certain folders can hold different types of items, and your code should test for that.
There is simply no reason to use "Set olApp = New Outlook.Application" when "Set olApp = Application" or "Set olApp = Outlook.Application" is more appropriate. The Outlook Application Object is directly available (we are coding this inside Outlook, after all), why create a new instance? Or at the very least, even if Outlook doesn't create a new instance, why not save a few processor cycles confusing Outlook and just get right to the point? For similar reasons, you shouldn't need to use GetObject or CreateObject.
The closest analogy I can think of is Occam's Razor, slightly modified: "Objects must not be multiplied beyond necessity."
The default Inbox can hold appointments, mail items, unread tasks, etc. Not checking to make sure the particular object you are working with is a mail item will eventually lead to code that breaks.
Here is my updated version showing appropriate assignment of Outlook Application Object, and defensively checking to make sure the item being looked at is a mailitem before proceeding. I also destroyed one variable (olItms) which was left untouched in the previous code.
Sub myLoop_2()
'Declaration
Dim olApp As Outlook.Application
Dim olNs As Outlook.NameSpace
Dim olFldr As Outlook.MAPIFolder
Dim olItms As Outlook.Items
Dim olMail As Object
Set olApp = Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set olFldr = olNs.GetDefaultFolder(olFolderInbox)
Set olItms = olFldr.Items
'Loop the items
For Each olMail In olItms
If TypeOf olMail Is Outlook.MailItem
'Here you need to use olMail Object to inspect individual mails inside the Inbox
End If
Next olMail
'Release the objects appropriately
Set olItms = Nothing
Set olFldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
I would also like to add, as a side note, that my post was inspired not just because of the code provided, but also in part because I submitted a comment to the above mentioned blog post and mentioned these specific critiques, and so far my comment hasn't been approved (it's been a week?). I don't understand why people create blogs and have comment boxes, only to ignore their commenters.
On this blog (and this site in general), there's a "plain text" option so you can easily cut and paste the code found here. Not so on every other site, I found out. The CSS code (or whatever it is) used to generate the code samples on DeVa's blog makes cutting and pasting it an unpleasant experience. When I copied it to create this post, all of the line numbers get copied as well, so it requires a lot of hand-editing. Why post code and make it difficult for others to actually use it? I feel bad for anyone who needs to copy those subs on a regular basis.
Update: The trackback for this post appears on DeVa's blog. Let's see if it stays.





Hi
I would declare the line
Dim olMail As Object
as
Dim olMail As outlook.MailItem
Kind regards
Christian
Good point, that's the other way to make sure you are only acting on MailItems.