Outlook forms: How to create a custom Outlook form using VBA
Because it is composed of different windows, panes, and form regions, the Outlook UI presents a complex UI model to the developer. Despite these options, a common customization request is for custom forms to display the various Outlook items. Today, we’ll take a look at Outlook forms and how you can customize them.
- What are Outlook forms?
- Built-in vs. custom Outlook forms
- How to create a custom Outlook form
- How to enumerate/access user forms
- How to remove custom items
- Useful events to work with Outlook forms
- How to access form items
Outlook forms the UI elements used to collect and display item information in Outlook. By items, I mean Outlook “data” types:
Each of these have their own, built-in (or standard) form. Built-in forms handle greater than 82% of all user needs (approximately… based on my own, non-scientific analysis).
For 15% of the remaining needs, you can create custom forms that display data and process logic according to your needs. The other 3%? Nothing can be done.
Built-in forms are the forms Outlook provides out-of-the-box. They include standard behaviors and are the forms you already know as a user of Outlook.
Custom forms are forms created by you or another developer that:
- Modifies or extends the functionality of a built-in form
- Is a brand-spanking new creation developed from scratch
The typical scenario for a custom form is to modify and extend a built-in form.
Outlook provides a tool called the Outlook form designer. In this example, I’ll show you how to use a built-in form as the starting point for a custom form. I’ll assume you have Outlook open already. Just follow these steps and we’ll knock this out together:
- Right click the Outlook ribbon and select Customize the Ribbon. Click OK.
- Click the Developer ribbon tab. In the Custom Form button group, click the Design a Form button. In the Design Form dialog, select the Contact form and click Open to open the form in the Outlook Form Designer.
- We’ll add a new page to the standard Contact form. Click the tab labeled (P.2).
- In the Form
Designer ribbon, find the Tools group and click the Control Toolbox.
- Add the following controls to the form (use the Property Sheet to change properties):
- In the Tools group click the Field Chooser button. Now in the Field Chooser, find the Notes field and add to the new page (P.2). Your Outlook custom form should look like this (or close to it).
- Last step. Click Publish in the form designer ribbon. In the Publish Form dialog box, select Personal Forms Library. Enter My Contact Form as the Display Name and MyContactForm as the Form name. Click Publish. Close the form designer. Click No and do not save your changes.
To utilize the form, you need to navigate to the Contacts (or People) folder, access the Developer tab, and click the Choose Form button. From here, you can select the My Contact Form to create a new contact.
You can enumerate and access an Outlook form using Collaborative Data Objects (CDO). The following is VBA that uses CDO 1.21 to enumerate all forms in a specified Outlook folder.
Sub ListForms(fld As Outlook.MAPIFolder) 'From https://www.outlookcode.com/codedetail.aspx?id=1683 Dim strList As String ' requires reference to Collaboration Data Objects library ' (CDO 1.21) Dim cdoSession As MAPI.Session Dim cdoFolder As MAPI.folder Dim cdoFilter As MAPI.MessageFilter Dim cdoMessages As MAPI.Messages Dim cdoMessage As MAPI.Message Const CdoPR_Form_Name = &H6800001E On Error Resume Next Set cdoSession = CreateObject("MAPI.Session") cdoSession.Logon "", "", False, False Set cdoFolder = cdoSession.GetFolder(fld.EntryID, fld.storeID) Set cdoMessages = cdoFolder.HiddenMessages For Each cdoMessage In cdoMessages If cdoMessage.Type = _ "IPM.Microsoft.FolderDesign.FormsDescription" Then strList = strList & vbCrLf & _ cdoMessage.Fields(CdoPR_Form_Name).Value End If Next If Len(strList) > 0 Then strList = Mid(strList, 2) Else strList = "No forms found in folder" End If MsgBox strList, vbInformation, "Forms in " & fld.Name & " folder" cdoSession.Logoff Set cdoSession = Nothing Set cdoFolder = Nothing Set cdoMessage = Nothing Set cdoMessages = Nothing End Sub
Once again, we’ll need to utilize CDO to handle this task. The trick is that personal forms are stored with a message class value of “IPM.Microsoft.FolderDesign.FormsDescription”. So, let’s find items with this message class and delete them.
Public Sub DeleteForms 'From microsoft.public.outlook.program_vba (Ken Slovak) 'https://groups.google.com/forum/?hl=en&fromgroups= '#!topic/microsoft.public.outlook.program_vba/NWjL2UpcNJ8 Dim oSession As MAPI.Session Dim oInbox As MAPI.Folder Dim oRoot As MAPI.Folder Dim oStore As MAPI.InfoStore Dim oViews As MAPI.Folder Dim oMessage As MAPI.Message Dim oFolders As MAPI.Folders Dim oMessages As MAPI.Messages Dim sMessageClass As String Set oSession = CreateObject("MAPI.Session") oSession.Logon "", "", False, False Set oInbox = oSession.Inbox Set oStore = oSession.GetInfoStore(oInbox.StoreID) Set oRoot = oStore.RootFolder Set oFolders = oRoot.Folders 'for Outlook 2003 use "IPM_Common_Views" instead Set oView = oFolders.Item("Common Views") Set oMessages = oView.HiddenMessages For Each oMessage In oMessages If oMessage.Type = "IPM.Microsoft.FolderDesign.FormsDescription" Them sMessageClass = oMessage.Fields(&H6800001E) If sMessageClass = "IPM.Note.xxx" Then oMessage.Delete Exit For End If Next oSession.Logoff 'now set all objects = Nothing End Sub
In a custom Outlook form, you program against the form object and its events. You don’t have access to the Outlook application and events.
When you use a custom form, Outlook only supports the Click event for controls. This is a natural choice for buttons but not optimal for controls like the combo box. You write the code by inserting it into a form’s VBScript editor. You need to have the Outlook form open in the Form Designer and click the View Code button found in the Form group of the Developer tab.
Here is the natural choice for a code sample of button control.
Sub CommandButton1_Click() msgbox "Hello World" End Sub
If you want to respond to changes of Outlook properties, you can do it. You need to create a method that responds to the form item’s PropertyChange event. The event receives the name of the Outlook property that changed. You must check the value to determine if it is the property you want and respond accordingly.
Sub Item_PropertyChange(ByVal Name) Select Case Name Case "Subject" ' your code goes here, for example: MsgBox Item.Subject, , "The subject is ..." Case "Categories" ' more code goes here, for example: MsgBox Item.Categories, , "The categories are..." ' continue with Case statements for other properties ' whose values you want to monitor End Select End Sub
Outlook lets you create custom properties to support your custom data needs. You can respond to changes to custom properties in the same manner as you do with standard properties. The only difference is the two properties reside in separate collections. Thus, they have separate change events.
Sub Item_CustomPropertyChange(ByVal Name) Select Case Name Case "MyProp1" strMyProp1 = Item.UserProperties("MyProp1") Select Case strMyProp1 Case "Text1" ' code to react to the MyProp1 ' string property having a value of "Text1" Case "Text2" ' code to react to the MyProp1 ' string property having a value of "Text2" Case Else ' code to handle other values of MyProp1 End Select Case "MyProp2" ' code to handle a change in MyProp2 goes here ' continue with Case statements for other properties ' whose values you want to monitor End Select End Sub
You can learn more about each these events here.
Within the form’s VBScript, you can access form pages and controls by name.
Text Boxes reside within a form page’s Controls collection. First, reference the page, then call the controls section and pass the text box name.
Sub CommandButton1_Click() Set Page = Item.GetInspector.ModifiedFormPages Set Cntl = oPage("P.2").Controls("TextBox1") Cntl.SetFocus Cntl.Text = "Hello World!" Set Cntl = Nothing Set Page = Nothing End Sub
Combo Boxes are accessed in the same manner as text boxes. But, maybe the best place to access them is the Form’s Open event (ah, and you thought maybe I forgot about this useful event!)
Sub Item_Open() Set FormPage = Item.GetInspector.ModifiedFormPages("P.2") Set Control = FormPage.Controls("ListBox1") Control.PossibleValues = " Bono;Edge;Adam;Larry" End Sub
The memo field of an Outlook item is known as the Body to code. You can access it and change its value easily.
Sub CommandButton1_Click() Item.Body = Item.Body & vbCrLf & "I was clicked at ::" & now() End Sub
Outlook forms – Available for solutions but…
I didn’t editorialize as I went along because I think it is obvious. Outlook forms exist and have been around for a long time. But, easier and more powerful options exist. I recommend using this for quick and dirty solutions limited to a small set of users. Maybe 1, or zero.
- Part 1: Outlook add-in development: Outlook Application and base objects
- Part 2: Creating custom Outlook views
- Part 3: Creating custom Outlook forms
- Part 4: Outlook UI – Explorer and Inspector Windows. What is customizable?
- Part 5: Customizing Outlook main menu, context menus and Backstage view
- Part 6: Creating custom Outlook ribbons and toolbars
- Part 7: Advanced view regions for Outlook 2013 – 2003
- Part 8: Advanced form regions for Outlook 2013 – 2003
- Part 9: Working with Outlook Accounts, Stores, Folders and Items
- Part 10: Working with Outlook calendar
- Part 11: Working with Outlook tasks