If you are building an Outlook Add-In application with Visual Studio, it’s likely that at some point you will want programmatic control over the information that Outlook shows in a specific email folder.
For instance, let’s say that you have code that automatically backs up sent emails to a custom folder hierarchy. So if the email you sent includes sample code, then the email should be automatically backed up into a custom sub-folder called “Sample Code” that exists within your custom “Programming” folder within your Outlook mailbox. If that sounded confusing, here’s an image of what I’m talking about:
+Mailbox |_Programming |_Notes |_Sample_Code |_General |_Sent Items |_Etc...
This article will show you how to manage the columns of information shown in the list of emails for the custom folders, including how to populate the columns with custom fields.
I won’t cover how to back up your emails using the Outlook add-in component. If you are interested in further details on this topic you can read more about doing so in my ongoing series of articles that cover using Visual Studio 2010 to develop outlook add-in components.
So here is an example of the columns that should be shown for the list of emails in each folder:
As you can see, the first six columns should be a selection of the standard columns that come with Outlook such as From, To, Subject, etc. However if you look at the last four columns, you can see that we also want to show custom columns that we have added to our emails as UDFs (User Defined Fields).
Your code that backs up each email is responsible for adding the necessary UDFs to each message. If you want information on how to back up your email messages, see an article I wrote titled: Outlook Custom Add-In to Archive Emails on Send Based on Keyword in Subject Line (Visual Studio 2010).
So how’s it done?
For starters you will need to add a custom method to your Outlook Add-in’s Application.Startup event. This event is triggered when a user first opens Outlook.
It’s at this point we want our code to trigger that will loop through each of our custom sub-folders to ensure that the correct columns of email information are shown in each.
Traversing the Outlook Folder Hierarchy
The code to handle the looping though the folders is quite self explanatory. You can get the root mailbox folder using the command:
Dim objFolder As Outlook.Folder = Application.Session.DefaultStore.GetRootFolder()
Then to get the instance of your custom “Programming” folder, you can get it by name from the Outlook.Folders collection:
Dim Programmingfolder As Outlook.Folder = objFolder.Folders("Programming")
Extending on this logic you can address each custom sub folder in the folders collection of the custom “Programming” folder variable that we populated in the code above using a simple loop:
Dim tmpSubFolder As Outlook.Folder = fldParentFolder.Folders(x)
Once you have the instance of the sub folder that you need to address, use the CurrentView object to address the default Outlook view for the folder.
In order to ensure your user sees a consistent list of columns you should remove all existing folders in the Outlook CurrentView and then re-add the list of folders that the user should see.
Removing and then re-adding the list of fields may seem a bit extreme, but Outlook allows users to add/remove/move columns at will. In a situation where you want to present specific information to the user in a reliable manner, it is important that the correct information is shown regardless of the user’s actions.
One further point to note: while looping through the existing ViewField and removing columns, remember that Outlook will throw an error if you try to remove all of the columns at once. So in the column removal routine you need to check when the last record is about to be removed so that you can add a new column is added. This column should be the first column that you want to appear in your list of emails.
You can see the detail for handling the column removals in the method called ClearTableViewSetFirst( that is shown in the code below.
Adding Built-in Outlook Fields to your ViewField
When you have finished removing the columns you need to add the six columns of built in Outlook email information that we want to show (ie: the From, To, and Subject lines). Adding columns of built-in Outlook email information is actually quite straightforward. Simply append them by name to your currently displaying ViewField using the ViewField.Add(“”) method.
If you are using the ViewField.Add function, watch out that you are not adding the same field twice, or you will get the COM exception: “An attempt has been made to add the same field more than once.”
Adding the Email UDF’s to your Outlook ViewField
Once you have finished adding the built in Outlook columns, you will need to append the four custom columns. In your previously written email back-up logic you will have saved information for each email as a User Defined Field, so at this point the idea is to hook up the Outlook ViewField with your custom UDFs.
The process is a bit tricky, but is clearly shown in the code below in a method called SetSubFolderColumns(. This method checks to see if the custom field already is defined, and if not, uses the UserDefinedProperties.Add( method to add the UDF as an available field.
When the UDF has been set as an available field, the code appends the field at the end of the existing list of fields using the ViewFields.Insert( method.
While creating UDFs, make sure your user defined property does not clash with already existing Outlook columns such as From, To, Cc, Subject, etc. If you try to set a custom property column with an existing column name you will get a COM exception with the text “A field with this name already exists in the “Frequently-used fields” field set. Enter a different name.”
Here is the code for a VS2010 Outlook Add-in component that will maintain a set of fields (both custom UDFs and inbuilt fields) within a set of folders:
Public Class ThisAddIn Private Sub ThisAddIn_Startup() Handles Me.Startup End Sub Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown End Sub Private Sub Application_Startup() Handles Application.Startup Dim objFolder As Outlook.Folder = Application.Session.DefaultStore.GetRootFolder() Dim Programmingfolder As Outlook.Folder = Nothing Programmingfolder = objFolder.Folders("Programming") LoopThroughSubFolders(Programmingfolder) End Sub Private Sub LoopThroughSubFolders(ByVal fldParentFolder As Outlook.Folder) Dim strAddFirstField As String = "From" Dim strAddSecondField As String = "To" Dim strAddThirdField As String = "Cc" Dim strAddFourthField As String = "Bcc" Dim strAddFifthField As String = "Subject" Dim strAddSixthField As String = "Received" Dim strColOne As String = "EmailId" Dim strColTwo As String = "VB" Dim strColThree As String = "C#" Dim strColFour As String = "IsCodeIncluded" Dim intSubFolderCnt As Int32 = fldParentFolder.Folders.Count For x As Int32 = 1 To intSubFolderCnt Dim tmpSubFolder As Outlook.Folder = fldParentFolder.Folders(x) Dim tblView As Outlook.TableView = tmpSubFolder.CurrentView() ClearTableViewSetFirst(tblView, strAddFirstField, strAddFifthField) tblView.ViewFields.Add(strAddSecondField) tblView.ViewFields.Add(strAddThirdField) tblView.ViewFields.Add(strAddFourthField) tblView.ViewFields.Add(strAddFifthField) tblView.ViewFields.Add(strAddSixthField) tblView.Save() tblView.Apply() SetSubFolderColumns(tmpSubFolder, strColOne) SetSubFolderColumns(tmpSubFolder, strColTwo) SetSubFolderColumns(tmpSubFolder, strColThree) SetSubFolderColumns(tmpSubFolder, strColFour) Next End Sub Private Sub ClearTableViewSetFirst(ByRef tblView As Outlook.TableView, ByVal strAddFirstField As String, ByVal strAddAlternateField As String) For x As Int32 = tblView.ViewFields.Count To 1 Step -1 If x = 1 Then Dim vfPrimaryField As Outlook.ViewField = Nothing Try vfPrimaryField = tblView.ViewFields(strAddFirstField) Catch ex As Exception End Try If vfPrimaryField Is Nothing Then tblView.ViewFields.Add(strAddFirstField) Else tblView.ViewFields.Add(strAddAlternateField) tblView.ViewFields.Remove(1) tblView.ViewFields.Add(strAddFirstField) End If End If tblView.ViewFields.Remove(x) tblView.Save() tblView.Apply() Next End Sub Private Sub SetSubFolderColumns(ByRef fldChildFolder As Outlook.Folder, ByVal strCustomColumnName As String) Dim tblView As Outlook.TableView = fldChildFolder.CurrentView Dim udfPrimaryProperty As Outlook.UserDefinedProperty = fldChildFolder.UserDefinedProperties.Find(strCustomColumnName) Dim vwfSearchField As Outlook.ViewField = Nothing Try vwfSearchField = tblView.ViewFields(udfPrimaryProperty.Name) Catch ex As Exception End Try If udfPrimaryProperty Is Nothing Then udfPrimaryProperty = fldChildFolder.UserDefinedProperties.Add(strCustomColumnName, Outlook.OlUserPropertyType.olText, Outlook.OlFormatText.olFormatTextText, "") vwfSearchField = tblView.ViewFields.Insert(strCustomColumnName.Replace(" ", "%20"), (tblView.ViewFields.Count + 1)) End If If vwfSearchField Is Nothing Then vwfSearchField = tblView.ViewFields.Insert(udfPrimaryProperty.Name, (tblView.ViewFields.Count + 1)) vwfSearchField.ColumnFormat.Width = 20 tblView.Save() tblView.Apply() End If End Sub End Class