Ty Anderson

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?

Outlook forms the UI elements used to collect and display item information in Outlook. By items, I mean Outlook “data” types:

  • Mail
  • Appointments
  • Contacts
  • Tasks
  • Notes
  • Posts
  • Etc.

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 vs. custom Outlook forms

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:

  1. Modifies or extends the functionality of a built-in form
  2. 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.

How to create a custom Outlook 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:

  1. Right click the Outlook ribbon and select Customize the Ribbon. Click OK.
  2. 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.
  3. We’ll add a new page to the standard Contact form. Click the tab labeled (P.2).
  4. In the Form
    ribbon, find the Tools group and click the Control Toolbox.
  5. Add the following controls to the form (use the Property Sheet to change properties):
    1. Label
    2. TextBox
    3. Button
  6. 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).

Outlook custom form

  1. 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.

How to enumerate/access user forms

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 http://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 & _
        End If
    If Len(strList) > 0 Then
        strList = Mid(strList, 2)
        strList = "No forms found in folder"
    End If
    MsgBox strList, vbInformation, "Forms in " & fld.Name & " folder"
    Set cdoSession = Nothing
    Set cdoFolder = Nothing
    Set cdoMessage = Nothing
    Set cdoMessages = Nothing
End Sub

How to remove custom items

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)

  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
        Exit For
    End If
 'now set all objects = Nothing
End Sub

Useful events to work with Outlook forms

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.

How to access form items (edit boxes, combos, memos, etc.)

Within the form’s VBScript, you can access form pages and controls by name.

Text Boxes

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.Text = "Hello World!"
  Set Cntl = Nothing
  Set Page = Nothing
End Sub

Combo Boxes

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

Memo Field

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.


Outlook 2013 add-in development in Visual Studio 2012 for beginners

You may also be interested in:


  • https://secure.gravatar.com/avatar/c401f036bd9a1771fcb5b8fe564a4460?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G CC says:

    So frustrated, please help. Attachments re-arrange themselves EVERY TIME I assign an Outlook task to someone else!! We have found the custom form to be very useful and every new task we create in Outlook is via the custom form. We assign this task back and forth between employees every day. Each “task” is a client file with information typed and attachments inserted into different parts below relevant lines of text (could be PDFs, JPGs, emails, or other docs). WELL, ever since switching to Outlook 2013, when we go to “Assign Task,” it immediately drops any and all attachments (which, again, we have pasted purposefully in specific parts of the task) TO A ROW ALL TOGETHER AT THE BOTTOM OF THE PAGE!! Why is this happening?!? THIS DID NOT HAPPEN IN OUTLOOK 2010 using the same custom form! We are on an exchange server. Please help if you have any suggestions, thanks!

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:

    Hi CC

    I really don’t know why this occurs in Outlook 2013. If it is possible to see your code, maybe I can offer some assistance.


  • https://secure.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?s=32 RM says:

    I am trying to send bunch of meeting invite to different users from Public Calendar. Everything is working fine but I have a problem of reminder. I want all the recipients will get reminder but not me (meaning organizer). I have tried different code but nothing is working.
    Enclosed please find my code:
    Sub Macro1()

    ‘ Macro1 Macro

    Dim olApp As Outlook.Application
    Dim olNS As Namespace
    Dim olFolder As MAPIFolder
    Dim olApt As AppointmentItem
    Dim objAttendees As Outlook.Recipients

    Set olApp = CreateObject(“Outlook.Application”)
    Set olNS = olApp.GetNamespace(“MAPI”)
    Set olFolder = olNS.GetDefaultFolder(olFolderCalendar).Folders(“WDS”)

    Dim imyMailItem As Outlook.MailItem
    Dim myOlApp As Outlook.Application
    Set myOlApp = Outlook.Application

    Dim r As Long

    ‘ late bound constants
    Const olAppointmentItem = 1
    ‘Const olBusy = 2
    Const olMeeting = 1

    ‘ Create the Outlook session
    ‘Set myoutlook = CreateObject(“Outlook.Application”)

    ‘ Start at row 2
    r = 2

    Do Until Trim$(Cells(r, 1).Value) = “”

    ‘ Create the AppointmentItem
    ‘Set myapt = myoutlook.CreateItem(olAppointmentItem)
    Set olApt = olApp.CreateItem(olAppointmentItem)
    Set olApt = olApt.Move(olFolder)
    Set imyMailItem = olApp.CreateItem(olMailItem)
    ‘ Set the appointment properties

    With olApt

    .Subject = Cells(r, 1).Value
    .Start = Cells(r, 2).Value
    .End = Cells(r, 4).Value
    .RequiredAttendees = Cells(r, 9).Value
    Set objAttendees = .Recipients
    .MeetingStatus = olMeeting
    ‘ not necessary if recipients are email addresses
    ‘ myapt.Recipients.ResolveAll
    .AllDayEvent = Cells(r, 7).Value

    For x = 1 To objAttendees.Count
    If objAttendees(x) .Organizer Then

    If Cells(r, 6).Value 0 Then
    .ReminderSet = True
    .ReminderMinutesBeforeStart = Cells(r, 6).Value
    .ReminderSet = False
    End If
    .ReminderSet = False
    End If
    ‘End If

    .Body = Cells(r, 1).Value
    r = r + 1
    On Error Resume Next
    End With


    End Sub


    Any suggestion or help will be greatly appreciated.
    Thanks in advance!!

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:

    What if, after sending the appointment to other users, you edit your copy of the appointment?
    You can remove the reminder and save it.

    Maybe something like this:

    On Error Resume Next

    .ReminderSet = False

    End With


  • https://secure.gravatar.com/avatar/4479c06cf135aad7f70592c04ce3069c?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Boris says:

    Hello Ty,

    I tried to follow your code, but face a problem I can’t find the reason for. I’m using Outlook 2010 and created a custom form like you explained above. An existing task with an additional, custom tab and a button on it. I saved this code in the Script editor window I get if I press the view code button:

    sub cb_SaveLog_Click()
    msgbox “Hello World”
    end sub

    If I try press “Run this Form” it works, I got a new tab with my button and the message box. But if I publish the form and create a new instance the button shows no reaction. Macro settings are on trust all, the lowest possible.

    Do you have a hint for me

    many thanks in advance


  • https://secure.gravatar.com/avatar/4479c06cf135aad7f70592c04ce3069c?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Boris says:

    Hello Try,
    I found out that it makes the difference where I save the task. In my personal library or in the group mail box. I tried a lots of possible combinations and must now agree with you that this stuff is quite unpredictable and no solution I can implement for all users within our department. Sometimes it works, sometimes not. That’s a little bit frustrating. I go now (again) back to zero and think about another solution.
    Best regards

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:


    I’m glad to hear you figured out this much.
    My preference is to steer clear of VBA forms entirely!


  • https://secure.gravatar.com/avatar/fe009324fc7cc146d7d9b1e9f3fb750e?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Andrea Dahlkamp says:

    I have created and used successfully the custom calendar forms in Outlook 2010. I have published the form and set it as a default successfully to a shared calendar. All Outlook 2007 and Outlook 2010 users in our organization can successfully use the form. One individual in our organization upgraded to Outlook 2013 and can no longer use the custom form. Is there a fix to this?

    Thank you,

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:

    Hello Andrea,

    Like you, I’d expect this work without issue.
    What steps have your tried to resolve it?

    I think you should clear the custom forms and reinstall the form.

    That might do the trick.

  • https://secure.gravatar.com/avatar/cb8aef00cc279c267407e504a69098df?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Trevor says:


    You say ” But, easier and more powerful options exist”.
    Do you have any articles about these other options?

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:

    Hi Trevor,

    I was trying to be subtle while referring to our Add-in Express for Office and .NET.
    Outlook forms is antiquated and not something I would recommend. I realize not everyone will agree with me but, hey, that’s why it’s my opinion and not gospel truth.

    If you are looking for articles, our blog is the right place.
    I recommend starting here and following the links that interest you:



  • https://secure.gravatar.com/avatar/562cda3f516326324e49bc2ca180c772?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Gary A says:

    Your instructions on using Item_PropertyChange(ByVal Name) or Item_CustomPropertyChange(ByVal Name) do not work for me. I’m on Outlook 2010. I’ve created multiple forms on Outlook 2003 with no problem. But Outlook 2010 does not work for me. I created a simple test form so I could test if the forms code works. It has two option buttons and two combo boxes. Both of the combo buttons are set up as not visible so that if one button is chosen, one of the comboboxes will become visible. This is my code.

    Sub Item_PropertyChange(ByVal Name)
    Set MyPage = GetInspector.ModifiedFormPages(“Message”)
    If MyPage.OptionButton1.value = True Then
    MyPage.ComboBox1.visible = True
    MyPage.ComboBox2.visible = False
    ElseIf MyPage.OptionButton2.value = True Then
    MyPage.ComboBox1.visible = False
    MyPage.ComboBox2.visible = True
    End If
    End Sub

    It doesn’t work.

  • Hello Gary,

    Export the form to a .FRM file, rename the file to .TXT and send it to me using the contact form at https://www.add-in-express.com/support/askus.php.

  • https://secure.gravatar.com/avatar/67739b51810234b945d04e04df583a21?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ericka says:

    I have created, successfully, a custom task for my projects I have utilized multiple pages.Is there a way to push the individual task to an excel template? If I print it will list every userdefined field name with entry, custom and standard. I want that pushed to an excel spreadsheet template for each single task as I want them printed. I intend to use it as cover sheet for completed projects in the hard file and save as PDF with other scanned files. Every reference I make to individual userdefined fields stays blank. Is there an easy way to refer to the custom form and send all form fields of a single to excel template?

  • https://secure.gravatar.com/avatar/c68f03884efb33fd95bcfbd9f1078c07?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ty Anderson says:

    Hi Ericka,

    Please review this article:

    It shows how to export Outlook tasks to an Excel spreadsheet.


  • https://secure.gravatar.com/avatar/082deb36e52ce2ce2267dd77e28da688?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Rampradeep says:

    please tell me how to create custom tab in outlook 2007 using vba code.

  • https://secure.gravatar.com/avatar/f15dfb389c191f32f8ea68ee3b35bed7?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Rampradeep says:

    Hai Anderi Smolin i have tried this but i am getting error like “object is required” in the line-ActiveProject.SetcustomUI(ribbonXml).please solve this problemm.The entire code is like.
    Private Sub AddHighlightRibbon()
    Dim ribbonXml As String

    ribbonXml = “”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + ” ”
    ribbonXml = ribbonXml + “”

    ActiveProject.SetCustomUI (ribbonXml)
    End Sub

  • Ah, that’s my fault: the link targets MS Project, not Outlook. I’m really sorry.

    As to Outlook, at https://msdn.microsoft.com/en-us/library/aa338202.aspx they say: In the case of Outlook, only COM add-ins can customize the Fluent UI. That is, you can’t use VBA to create a custom tab in Outlook.

  • https://secure.gravatar.com/avatar/f15dfb389c191f32f8ea68ee3b35bed7?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Rampradeep says:

    Hai Andrei i have seen in one of the site but i am not getting how to create COM AddIn for outlook 2010 with in VBE application.
    can you tell me the steps how to do that.

  • https://secure.gravatar.com/avatar/f15dfb389c191f32f8ea68ee3b35bed7?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Rampradeep says:

    Hai Andrei …k then can we create COM AddIn with in VBE application for outlook 2010.please let me know.

  • https://secure.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Rampradeep,

    It is not possible to create a COM add-in by using Visual Basic for Applications (VBA). COM add-ins can be built using any programming language that can create COM components, e.g. C/C++, C#, VB.NET, Delphi, Visual Basic 6.

Post a comment

Have any questions? Ask us right now!