How to create an Outlook task, appointment or note from an email
In the first installment of this series, Outlook 2010 addin development: customizing Ribbon & toolbar in a single plugin, we took the first step in building the Ty Actions Outlook Add-in. If you followed along, you have a beautiful custom Outlook ribbon and a custom a command bar that will impress your users… at least until they click a button. In this, part 2, of the series, we will correct this issue by writing some code. This code will fulfill the first two requirements for the add-in. If you don’t remember what they are, let’s review:
- Provide the capability to create a task, appointment, or note from an email.
- Extend the default “Create task” functionality to do more than Outlook does by default. I know, this is nice and vague but it will take a more definitive shape soon enough.
- Provide custom Outlook toolbars (ribbon or commandbar) for Explorer and Inspector windows.
- Support both Outlook 2007 and Outlook 2010.
We already completed #3 and #4. Apparently, we are working backwards. I guess I like to begin with the end in mind. Also, as I mentioned in Part 1 would probably happen, the requirements have changed to include what I’m calling the Contact Info form.
The idea of this Outlook custom form is to display contact info when you select an email in the Outlook Explorer window. As you move about the inbox and select different emails, the add-in will check your default Contacts folder for matching email address. If it finds a match, the add-in displays the Contact Info form. Otherwise, the form remains hidden. To keep our requirements list current, we’ll add the following:
5. Create a custom form to display the sender’s contact info from the currently selected email.
Alright. I’m feeling pretty good about our requirements and the fact that this will be a useful Outlook add-in. Let’s get to it then:
Creating an Outlook custom form: Contact info form
In the Ty Actions Visual Studio project, add a new Advanced Form Region. This project item template allows you to use a custom .NET Windows form to extend the Outlook UI. In our case, we will build a custom Outlook form region that displays inside the Explorer window… in the bottom of the preview pane.
You add the Advanced Form Regions in the same manner you add any new item to VS project. Form the VS menu, click Project | Add New Item…
In the Add New Item dialog box, expand Add-in Express Items and select the Outlook node. There, you will find the ADX Outlook Form template. Be sure to name the form ContactInfo. After you click Add, Visual Studio will display the following warning:
This message is our way of reminding you to add an Outlook Forms Manager component to the Add-in Module. We’ll take care of that in a moment. For now, click the OK button and we’ll complete the form design.
The ContactInfo form is ADXOlForm which inherits from Windows Forms. So, you can use any .NET controls (out-of-the-box from Visual Studio or 3rd Party controls) to design some killer Outlook user interfaces. Today’s sample add-in will not be killer but it will be functional.
Our Outook ContactInfo form has 10 labels used to display contact info. Building it might take five minutes… it’s plenty easy to do as you will discover by completing these steps.
- Add a Label control to the form and change these properties:
- Text = Full Name:
- TextAlign = TopRight
- Bold = True
- Add a Label control to the form and change these properties:
- Text = Title:
- TextAlign = TopRight
- Bold = True
- Add a Label control to the form and change these properties:
- Text = Company:
- TextAlign = TopRight
- Bold = True
- Add a Label control to the form and change these properties:
- Text = Business Phone:
- TextAlign = TopRight
- Bold = True
- Add a Label control to the form and change these properties:
- Text = Mobile Phone:
- TextAlign = TopRight
- Bold = True
- Add a Label control to the form next to the Full Name label.
- Name = lblFullName
- Text = Full Name Goes Here
- Add a Label control to the form next to the Title label.
- Name = lblTitle
- Text = Title Goes Here
- Add a Label control to the form next to the Company label.
- Name = lblCompany
- Text = Company Name Goes Here
- Add a Label control to the form next to the Business Phone label.
- Name = lblBusinessPhone
- Text = Business Phone Goes Here
- Add a Label control to the form next to the Mobile Phone label.
- Name = lblMobilePhone
- Text = Mobile Phone Goes Here
Done correctly, our Outlook custom form looks like this:
Add Outlook Forms Manager to control custom forms
The Outlook Forms Manager is an Add-in Express component that manages the instances of our ContactInfo advanced Outlook form region. Thanks to this component, we do not need to write code to track all Outlook windows, create new instances of our custom form, display them, etc. Nope… all we need to do is add our form to the Outlook Forms Manager’s collection and configure some properties.
Display the AddinModule in design view. Add and Outlook Forms Manager control by clicking its icon in the AddinModule’s toolbar (you can also right-click on the design surface and select it in the context menu). Now, select the newly added AdxOlFormsManager1 control. In the Properties window, find the Items property and click the ellipsis button to open the collection editor.
Click the Add button to add a new item to the collection. Then configure the following properties:
- Cached = OneInstanceForAllFolders
- ExplorerItemTypes = Mail
- ExplorerLayout = BottomReadingPane
- FormClassName = TyActions.ContactInfo (or whatever you named your form)
Click the OK button and you’re done. Now, anytime we display the ContactInfo form, it will be visible in the bottom of the Outlook reading pane.
We are now ready to write code.
Coding for magic: writing business logic of Outlook add-in
To meet requirements #1 and #2, we need three custom methods. The methods are:
- CreateLinkedItem : This method does the hard duty of creating an Outlook item. Either a task, appointment, or note.
- AttachSelections: This method attaches the currently selected email into the body of the item created in CreateLinkedItem.
- GetContactInfo: This method searches the default contacts folder for a contact with an email address that matches the currently selected email.
None of these are too complicated. But just in case, I explain each one as we go along.
A bit of code setup: class-level variables
Before we write the method, we need a few class-level variables. Open the AddinModule.vb file and display its Code View. Add the follow “private members” to the class. I recommend cutting and pasting.
#Region "Private Members" Private _ContactFullName As String Private _Title As String Private _Company As String Private _BusinessPhone As String Private _MobilePhone As String Private _ValidContact As Boolean #End Region
These guys (the private members) are class properties that allow us to store contact info within the class. If ever I decide to let other objects access these values, we’ll implement property methods for them. For now, this works just fine.
Creating an Outlook task, appointment or note from a selected email
Outlook’s custom toolbar (ribbon and command bar) buttons call this method. The idea is to take the currently selected email and create an Outlook item. Add the following code to the AddinModule class.
VB.NET code example
Private Sub CreateLinkedItem(ByVal itemType As Outlook.OlItemType) Dim explorer As Outlook.Explorer = _ DirectCast(OutlookApp.ActiveExplorer, Outlook.Explorer) Dim sel As Outlook.Selection = Nothing Try sel = explorer.Selection Catch End Try If sel IsNot Nothing Then If sel.Count > 0 Then Dim email As Outlook.MailItem = TryCast(sel.Item(1), Outlook.MailItem) If email IsNot Nothing Then Select Case itemType Case Outlook.OlItemType.olAppointmentItem Dim olItem As Outlook.AppointmentItem = _ TryCast(OutlookApp.CreateItem(itemType), Outlook.AppointmentItem) olItem.Subject = "Appt: " & email.Subject olItem.Body = email.Body AttachSelections(olItem, sel) olItem.Display() Marshal.ReleaseComObject(olItem) Case Outlook.OlItemType.olTaskItem Dim olItem As Outlook.TaskItem = _ TryCast(OutlookApp.CreateItem(itemType), Outlook.TaskItem) olItem.Subject = "Task: " & email.Subject olItem.Body = email.Body olItem.ContactNames = email.ReceivedByName AttachSelections(olItem, sel) olItem.Display() Marshal.ReleaseComObject(olItem) Case Outlook.OlItemType.olNoteItem Dim olItem As Outlook.NoteItem = _ TryCast(OutlookApp.CreateItem(itemType), Outlook.NoteItem) olItem.Body = email.Subject & vbCrLf & email.Body olItem.Display() Marshal.ReleaseComObject(olItem) End Select Marshal.ReleaseComObject(email) End If End If Marshal.ReleaseComObject(sel) End If Marshal.ReleaseComObject(explorer) End Sub
The type of item is a parameter of the method. The code branches depending on the type specified using a Select statement. For Outlook appointment and task items, the code will use the email’s subject and body to fill the item’s same values. Also for these types, the method calls AttachSelections to embed the selected email into the new item.
For Outlook note items, the code combines the email subject and body. For notes, the subject property is read only. But this strategy will cause the email subject to become the note’s subject. Notes do not support embedded objects so we will not attempt to embed the source email. We’ll let it be.
Adding selected email items to a task or appointment
This method only receives love and attention from CreateLinkedItem. It requires an item and an Outlook Selection object as parameters. Add the following to the AddinModule class.
VB.NET code example
Private Sub AttachSelections(ByRef item As Object, ByRef sel As Outlook.Selection) Dim i As Integer Dim attachments As Outlook.Attachments = item.Attachments For i = 1 To sel.Count Dim itemToAttach As Object = sel.Item(i) attachments.Add(itemToAttach) Marshal.ReleaseComObject(itemToAttach) Next Marshal.ReleaseComObject(attachments) End Sub
When called, the first thing it does is count the number of items. It then loops and adds each item in the selection object’s Item collection to the passed Outlook item. That’s it and that’s all… for this method at least.
Searching for a contact item by an email address
This method accepts an email string as a parameter. It then gets to work rummaging around the user’s default contacts folder, looking for an Outlook contact with a matching email. If it finds one, it stores the info we want in the private members we added just a few minutes ago. It also returns True to let the calling method know it found a contact. If no contact is found, we set empty strings and return false. Here is the code to add to the AddinModule class.
VB.NET code sample
Friend Function GetContactInfo(ByVal email As String) As Boolean If String.IsNullOrEmpty(email) Then Return False Dim found As Boolean = False Dim ns As Outlook.NameSpace = OutlookApp.GetNamespace("MAPI") If ns IsNot Nothing Then Dim contactsFolder As Outlook.Folder = _ DirectCast(ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts), _ Outlook.Folder) If contactsFolder IsNot Nothing Then Dim contactItems As Outlook.Items = contactsFolder.Items If contactItems IsNot Nothing Then Dim contact As Outlook.ContactItem = TryCast(contactItems.Find( "[Email1Address] = '" & email.ToString & "' or [Email2Address] = '" & email.ToString & "' or [Email3Address] = '" & email.ToString & "'"), Outlook.ContactItem) If Not IsNothing(contact) Then _ContactFullName = contact.FullName.ToString _Title = contact.JobTitle _Company = contact.CompanyName _BusinessPhone = contact.BusinessTelephoneNumber _MobilePhone = contact.MobileTelephoneNumber found = True Marshal.ReleaseComObject(contact) Else _ContactFullName = "" _Title = "" _Company = "" _BusinessPhone = "" _MobilePhone = "" found = False End If Marshal.ReleaseComObject(contactItems) End If Marshal.ReleaseComObject(contactsFolder) End If Marshal.ReleaseComObject(ns) End If Return found End Function
The only real trick here is to call the Find method of the ContactItems collection. That and to search ALL of the email fields.
Our business logic is done. Let’s wire our methods to our UI events and add-in events.
Wiring the code to Outlook events
We are on the home stretch. This last bit might require an additional 5-10 minutes. Let’s first add the code to our buttons.
The button click events
The easy way to attach the code to our custom Outlook buttons is to copy and paste the code below. In fact, this is exactly what I recommend you do.
VB.NET code sample
#Region "Button Events" Private Sub btnCreateTask_OnClick(ByVal sender As System.Object, _ ByVal control As AddinExpress.MSO.IRibbonControl, _ ByVal pressed As System.Boolean) Handles btnCreateTask.OnClick CreateLinkedItem(Outlook.OlItemType.olTaskItem) End Sub Private Sub cbbCreateTask_Click(ByVal sender As System.Object) _ Handles cbbCreateTask.Click CreateLinkedItem(Outlook.OlItemType.olTaskItem) End Sub Private Sub btnCreateAppointment_OnClick(ByVal sender As System.Object, _ ByVal control As AddinExpress.MSO.IRibbonControl, _ ByVal pressed As System.Boolean) Handles btnCreateAppointment.OnClick CreateLinkedItem(Outlook.OlItemType.olAppointmentItem) End Sub Private Sub cbbCreateAppointment_Click(ByVal sender As System.Object) _ Handles cbbCreateAppointment.Click CreateLinkedItem(Outlook.OlItemType.olAppointmentItem) End Sub Private Sub cbbCreateNote_Click(ByVal sender As System.Object) _ Handles cbbCreateNote.Click CreateLinkedItem(Outlook.OlItemType.olNoteItem) End Sub Private Sub btnCreateNote_OnClick(ByVal sender As System.Object, _ ByVal control As AddinExpress.MSO.IRibbonControl, _ ByVal pressed As System.Boolean) Handles btnCreateNote.OnClick CreateLinkedItem(Outlook.OlItemType.olNoteItem) End Sub #End Region
What we have here is six Click events that call CreateLinkedItem, each passing a parameter for the type of Outlook item to create.
Handling Explorer Selection Change
When the user selects a new item within the Outlook Explorer, Outlook triggers the ExplorerSelectionChange event. This event is the perfect location for the code that calls GetContactInfo and responds accordingly.
To make this happen for us we need 1) add Add-in Express Outlook Events component and 2) write code against it. To handle the first step, open the AddinModule in design view. Then click the Application Level Events button residing in the module’s toolbar (look at the end of the right-hand side… the one with the lightning bolt). In the options that display, click the Microsoft Outlook Events button.
We now have a component that allows us to attach code to Outlook’s events. The only event we need is the ExplorerSelectionChange event. Add the following code to AddInModule.
VB.NET code example
Private Sub adxOutlookEvents_ExplorerSelectionChange(ByVal sender As System.Object, _ ByVal explorer As System.Object) Handles adxOutlookEvents.ExplorerSelectionChange Dim olExplorer As Outlook.Explorer = DirectCast(explorer, Outlook.Explorer) Dim sel As Outlook.Selection = Nothing Try sel = olExplorer.Selection Catch End Try If sel IsNot Nothing Then If sel.Count > 0 Then Dim email As Outlook.MailItem = TryCast(sel.Item(1), Outlook.MailItem) If email IsNot Nothing Then Dim form As ContactInfo = _ DirectCast(AdxOlFormsCollectionItem1.GetForm(olExplorer), ContactInfo) If form IsNot Nothing Then If Not GetContactInfo(email.SenderEmailAddress) Then form.Hide() Else With form .lblFullName.Text = _ContactFullName .lblTitle.Text = _Title .lblCompany.Text = _Company .lblBusinessPhone.Text = _BusinessPhone .lblMobilePhone.Text = _MobilePhone .Visible = True .Show() End With End If End If Marshal.ReleaseComObject(email) End If End If Marshal.ReleaseComObject(sel) End If End Sub
This event begins by testing for a valid Selection. If a Selection exists and its count is above 0, we are ready to proceed. We do so by grabbing the first item in the Selection collection. We could grab all of them but I will leave that to you as a challenge. It shouldn’t be too difficult should you choose to take it on.
Using the selected mail item, we grab a reference to the ContactInfo form. This ref The for a valid Selection. IF erence is made easy to achieve thanks to the AdxOlFormsCollectionItem’s GetForm method.
We then call GetContactInfo and branch the code depending on if we have a valid contact or not. If not, we simply hide ContactInfo. If we do have a valid contact, we fill labels and display the form. It’s quite elegant!
Outlook 2010 add-in in action
We are now done with the building and can take tour Outlook plug-in for a spin. I recommend that you build the project, register it on your system, and hit F5 to see it action. Or, you can watch me do this in the video below.
Video: Contact Info form in Outlook
Available downloads:
This sample addin was developed using using Add-in Express for Office and .net:
VB.NET – Ty Actions Outlook Add-in