Hey, Scripting Guy! How can I write a script that accesses all the subfolders in my Outlook Inbox?
— MB
Hey, MB. You know, after you’ve written a daily scripting column for nearly two years (have we mentioned the Hey, Scripting Guy 500th column celebration lately?) you learn that certain subjects are strictly off-limits. Discuss religion in a scripting column? Not a good idea. Politics? Don’t even think about it. The fact that you should never, ever put ice cream on top of cake? Forget it; making a statement like that is bound to create controversy.
Note. As long as we’re on the subject, you shouldn’t dip chocolate chip cookies in milk either, at least not if you intend to drink the milk afterwards. (Editor’s Note: In the opinion of this editor, which is really the only opinion that counts, that statement is completely inaccurate. We apologize to all of you who know how to eat cookies properly – soggy to the point where you can just barely get it to your mouth without it falling into the milk.) |
If we were smart (yes, yes we know: that’s a big if), we’d add recursive functions and subroutines to the list of things that we should never talk about. It’s not that recursive functions and subroutines aren’t useful; they are. (In fact, we have no idea how to answer your question without using recursion.) No, the problem isn’t that recursion is useless, the problem is that recursion is an absolute nightmare to try to explain. And, let’s face it, when you’re a Scripting Guy you have enough nightmares as it is. (Such as editors chasing after Scripting Guys with soggy chocolate chip cookies. Or just editors.)
On the other hand, it wouldn’t be very good form to start answering a question and then never finish answering it. So, we’ll tell you what, MB: we’ll give you a script that can access all the subfolders in your Inbox, but we won’t promise that we’ll be able to explain the workings of the script in nitty-gritty detail, at least not in today’s column. Deal? Deal.
Note. And you can get a brief introduction to recursion by taking a peek at the Microsoft Windows 2000 Scripting Guide. |
Let’s start out easy. (OK, relatively easy.) Here’s a script that simply returns the names of all the folders and subfolders found in your Outlook Inbox:
Const olFolderInbox = 6Set objOutlook = CreateObject(“Outlook.Application”) Set objNamespace = objOutlook.GetNamespace(“MAPI”)
Set objInbox = objNamespace.GetDefaultFolder(olFolderInbox)
Wscript.Echo objInbox.Name
GetSubfolders(objInbox)
Sub GetSubfolders(objParentFolder) Set colFolders = objParentFolder.Folders For Each objFolder in colFolders Set objSubfolder = objParentFolder.Folders(objFolder.Name) Wscript.Echo objFolder.Name GetSubfolders objSubfolder Next End Sub
Note. We should point out that this script assumes that Microsoft Outlook is already running. If that isn’t true (or at least isn’t something you should assume), then check out the Office Space article Starting a Script Regardless of Whether or Not Microsoft Outlook is Already Running to find out how to write a script that starts Outlook. |
You’re right: the script does start off simple enough, doesn’t it? We begin by defining a constant named olFolderInbox and setting the value to 6; we’ll use this constant to tell the script which Outlook folder we want to bind to. We then use these two lines of code to create an instance of the Outlook.Application object and to bind to the MAPI namespace (which happens to be the only namespace we can bind to):
Set objOutlook = CreateObject(“Outlook.Application”) Set objNamespace = objOutlook.GetNamespace(“MAPI”)
After we’ve connected to the MAPI namespace we then call the GetDefaultFolder method and bind to the Inbox:
Set objInbox = objNamespace.GetDefaultFolder(olFolderInbox)
And after that we simply echo back the name of the Inbox:
Wscript.Echo objInbox.Name
Piece of cake. (Albeit without ice cream on top of it.)
Unfortunately, though, this is where things start to get a little bit tricky. Our next step is to call the recursive subroutine GetSubfolders, passing along the object reference to the Inbox as the subroutine parameter:
GetSubfolders(objInbox)
Here’s what the GetSubfolders subroutine looks like:
Sub GetSubfolders(objParentFolder) Set colFolders = objParentFolder.Folders For Each objFolder in colFolders Set objSubfolder = objParentFolder.Folders(objFolder.Name) Wscript.Echo objFolder.Name GetSubfolders objSubfolder Next End Sub
Before we do anything else we should point out that, even though we passed the object reference objInbox, GetSubfolders appears to receive something named objParentFolder. Don’t worry about that: objParentFolder is just a variable name we apply to anything that gets passed to the subroutine. (See, we told you this was going to start getting a little weird.) If that bothers you, don’t sweat it: instead, check out the Sesame Script column Functions, Subroutines, and How to Call Them From Other Scripts for more details.)
Inside the subroutine the first thing we do is use this line of code to create a collection of all the top-level subfolders found in the Inbox:
Set colFolders = objParentFolder.Folders
Is it important to say “top-level” subfolders instead of just subfolders? Yes, it is. Suppose our Inbox looks like this:
Which of these folders do you suppose are part of the Folders collection? That’s right: only Sample and Test; that’s because they’re the only top-level subfolders in the Inbox. What about Test 2? Well, as a sub-subfolder Test 2 is actually part of the Folders collection for the Test folder: to get at sub-subfolders we need to access the Folders collection for all the top-level folders. That’s why we have to use a recursive function: we need to look at a folder, then look at any folders within that folder, then look at any folders within those folders.
Etc.
After retrieving the Folders collection we set up a For Each loop to walk through all the items in that collection. Inside that loop we start out by creating an object reference that binds us to the first folder in the collection:
Set objSubfolder = objParentFolder.Folders(objFolder.Name)
After connecting to that folder we can echo back the folder name; we can also do this:
GetSubfolders objSubfolder
Yes, we’re calling the subroutine GetSubfolders from inside the GetSubfolders subroutine. Why? Well, if the first folder in the collection is Sample we now need to see whether Sample has any sub-subfolders. This is the part where people’s eyes begin to glaze over, but that’s OK; there’s nothing wrong with simply having faith that this works. It all sounds extremely complicated, and it is. But fortunately VBScript takes care of the hard stuff for us.
When we’re all done we’ll get back a list of every folder (top-level or not) found in the Inbox:
Inbox Test Test 2 Sample
Of course, you didn’t just want the folder names, you wanted to be able to access all the items (e.g., all the mail messages) found in those folders. Hey, no problem. We won’t explain this revised script in any detail; we’ll just note that we use the Items collection to retrieve all the items in a folder and then, for each item, we echo back the Subject line. Obviously you can modify this script to echo back the sender’s name, the message text, or anything else you want to echo back.
Here’s the script:
Const olFolderInbox = 6Set objOutlook = CreateObject(“Outlook.Application”) Set objNamespace = objOutlook.GetNamespace(“MAPI”)
Set objInbox = objNamespace.GetDefaultFolder(olFolderInbox)
Wscript.Echo objInbox.Name
Set colItems = objInbox.Items
For Each objItem in colItems Wscript.Echo objItem.Subject Next
GetSubfolders(objInbox)
Sub GetSubfolders(objParentFolder) Set colFolders = objParentFolder.Folders For Each objFolder in colFolders Set objSubfolder = objParentFolder.Folders(objFolder.Name) Wscript.Echo objFolder.Name
Set colItems = objFolder.Items
For Each objItem in colItems Wscript.Echo objItem.Subject Next
GetSubfolders objSubfolder Next End Sub
OK. You kow, that wasn’t as bad as we thought it would be. Maybe tomorrow we will tackle the question: is there a God?
Or, then again, maybe we won’t.
0 comments