Building Applications with Microsoft Outlook Version 2002

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

 

Aa155615.odc_c11612730-cover(en-us,office.10).gif

Chapter 11: Using Visual Basic, VBA, or VBScript with Outlook

Randy Byrne
Micro Eye, Inc.

December 2002

Applies to:
    Microsoft® Outlook® 2002
    Microsoft Visual Basic® Buy this book

Summary: This article presents an excerpt from the book Building Applications with Microsoft Outlook Version 2002 by Randy Byrne. (115 printed pages)

Contents

The Application Object
The NameSpace Object
The Outlook Window (Explorer Objects)
The Panes Collection Object
The OutlookBarPane Object
The OutlookBarStorage Object
The OutlookBarGroups Collection Object
The OutlookBarGroup Object
The OutlookBarShortcuts Collection Object
The OutlookBarShortcut Object
The CommandBars Collection Object
Overview of Command Bars
The CommandBar Object
The CommandBarControls Collection Object
The CommandBarControl Object
The CommandBarButton Object
The CommandBarComboBox Object
The CommandBarPopup Object
The AddressLists Collection Object
The AddressList Object
The AddressEntries Collection Object
The AddressEntry Object
Using CDO to Obtain Recipients
The Folders Collection Object
The MAPIFolder Object
The Views Collection Object
The Items Collection Object
The PostItem Object
The MailItem Object
The DocumentItem Object
The AppointmentItem Object
The MeetingItem Object
The TaskItem Object
The TaskRequestItem Object
The ContactItem and DistListItem Objects
The JournalItem Object
The Item Window (Inspector Objects)
The Pages Collection Object
The Page Object
The Controls Collection Object
The Control Object
The UserProperties Collection Object
The ItemProperties Collection Object
The Recipients Collection Object
Automation
Where To Go from Here

This chapter primarily addresses the use of Microsoft® Visual Basic® Scripting Edition (VBScript) in Microsoft Outlook® forms. It looks at the objects of the Outlook Object Model and provides programming examples in VBScript or Visual Basic. Most of the code examples in VBScript can be extended directly in Outlook Visual Basic for Applications (VBA) or Visual Basic. Exceptions are noted accordingly. You should carefully consider the impact of the Outlook E-Mail Security Update on forms and application-level code. For additional information on the programmatic implications of the object model guard in Outlook 2002, see Chapter 13, "Distributing and Securing Applications."

This chapter is designed to give you the fundamental skills and knowledge you need to create collaborative applications using Visual Basic and VBScript. You'll find items demonstrating almost all the code examples in this chapter in the VBScript Samples folder. This chapter covers how to

  • Modify command bars.
  • Create a programmatic search.
  • Modify views.
  • Set folders programmatically for offline use.
  • Snooze and dismiss reminders.
  • Reference a folder collection or a folder in the Folder List.
  • Create, open, send, and post standard and custom items.
  • Open and close standard and custom forms.
  • Set and change field values in items.
  • Hide or show a form page.
  • Change the properties of a control on a page.
  • Specify the recipients of an item.

To open the VBScript Samples folder

In the Folder List, expand the Building Microsoft Outlook 2002 Applications folder, expand folder 4. Beyond the Basics, expand the VBScript folder, and then click the VBScript Samples folder.

The Application Object

The Application object sits at the top of the object model and represents the entire Outlook application. The Outlook Application object has several purposes:

  • As the root object, it enables you to reference other objects in the Outlook object hierarchy.
  • It provides methods such as CreateItem and CreateObject so that you can create new items and reference them without moving through the object hierarchy.
  • It provides methods for directly referencing the active Outlook window or form.

More Info   For a complete list and description of the methods, properties, and events for the Application object, see Microsoft Outlook Visual Basic Reference Help. Also see the Visio document entitled "Outlook 2002 Object Model Extended View" in the Outlook 2002 Object Model folder under the Visual Basic for Applications folder under the 4. Beyond the Basics folder. This object model diagram shows the properties, methods, and events for every object in the Outlook object model.

**Important **  Open the Application object item in the VBScript Samples folder to work directly with this code in Outlook.

Application Object Methods

This section covers the ActiveExplorer,ActiveWindow,AdvancedSearch,CopyItem,CreateItem,CreateObject and GetNameSpace methods.

Returning the active window

You can use the ActiveWindow method of the Application object to return the topmost active Outlook window. The ActiveWindow method returns either an Explorer or an Inspector object, depending on the actual active window.

'Get the Active Outlook Window
'The ActiveWindow object is the topmost window in the running
'Outlook instance
Sub GetOutlookActiveWindow_Click
    If TypeName(Application.ActiveWindow) = "Inspector" Then
        MsgBox "The active window is an inspector", vbInformation
    Else
        MsgBox "The active window is an explorer", vbInformation
    End If
End Sub

The following example sets the MyExplorer object to the currently active Outlook Explorer window, displays a message that indicates the active window type, and then redisplays the item window when the ShowOutlookActiveExplorer control is clicked:

Sub ShowOutlookActiveExplorer_Click
    Set MyExplorer = Application.ActiveExplorer
    MyExplorer.Display
    GetOutlookActiveWindow_Click()
    Item.Display
End Sub

Creating a standard item

You can use the CreateItem method of the Application object to create and return Outlook standard items such as a Message item, a Post item, or an Appointment item. The following example creates a Message item using the default editor and displays it when CreateAMailMessage is clicked:

Sub CreateAMailMessage_Click
    Set MyItem = Application.CreateItem(0)
    MyItem.Display
End Sub

The next simple example creates an HTML message.

Sub CreateHTMLMessage_Click
    Const olMailItem = 0
    Set myItem = Application.CreateItem(olMailItem)
    myItem.HTMLBody = ""
    myItem.Display
End Sub

It's useful to know that you can also create a Word Envelope message in code. The following example uses the CreateObject method to launch Word and display a Word Envelope message. From the standpoint of the message body, Word Envelope messages are equivalent to HTML messages.

'Creates a Word Message item and displays it
Sub CreateAWordMessage_Click
    Const wdNewEmailMessage = 2
    Dim objApp,objMsg
    Set objApp = CreateObject("Word.Application")
    Set objMsg = objApp.Documents.Add(,,wdNewEmailMessage)
    objApp.Visible = True
    objApp.ActiveWindow.EnvelopeVisible = True
End Sub

The following table lists the numeric values you use as arguments for the CreateItem method. You can also copy the CONST declarations in the Enum OlItemType section of the Outlook Constants item in the VBScript Samples folder and paste them into your code.

Type of Item Value
Appointment 1
Contact 2
Distribution List 7
Journal 4
Mail Message 0
Note 5
Post 6
Task 3

**More Info **  For more information about creating custom items, see "Items Collection Methods" later in this chapter.

Creating an Automation object

You can use the CreateObject method of the Application object to create Automation objects, such as Microsoft Excel, Microsoft Access, or Microsoft Word objects. You can also use the CreateObject method to create instances of custom ActiveX DLLs that extend the functionality of Outlook. The following example uses the CreateObject method to create an instance of Excel, adds a workbook, and then renames the first sheet in the workbook to Outlook CreateObject Example:

'Launch Excel with CreateObject
Sub LaunchExcel_Click
    Dim xLApp 'As Excel.Application
    Dim xLSheet 'As Excel.Worksheet
    Set xLApp = CreateObject("Excel.Application")
    If xLApp Is Nothing Then
        MsgBox "Could not create Excel Application", vbCritical
        Exit Sub
    End If
    xLApp.Workbooks.Add
    Set xLSheet = xLApp.Sheets(1)
    xLSheet.Name = "Outlook CreateObject Example"
    'Make the Excel Application window visible
    xLApp.Visible = True
End Sub

**Tip **  When you are writing Automation code for VBScript in Outlook forms, you can expedite the development process by using the VBA Editor in Outlook to write the code and then pasting the code into VBScript. As noted in the example above, you must place comment marks before the As keyword in the object type declarations, or VBScript will raise an error. The beauty of this approach is that you have all the IntelliSense features of the VBA Editor at your disposal, including auto list members, syntax checking, parameter information, quick information, and code formatting. Before you begin, set references to the appropriate object libraries by using the Tool menu's References command in the VBA Editor window.

Copying an item from the File System

The CopyItem method is new to Outlook 2002. It lets you copy an item from the File System to an Outlook folder. The following code example creates a Word document in the temporary folder, adds some text to the document, and then uses the CopyItem method to copy the document to the user's Inbox folder. Note that the CopyItem method accepts a string for the path to the destination folder instead of a MAPIFolder object.

Sub CopyItemToInbox_Click
   Dim objWord 'As Word.Application
   Dim objDoc 'As Word.Document
   Dim objSelect 'As Word.Selection
   Dim objDocItem 'As DocumentItem
   Set objWord = CreateObject("Word.Application")
   Set objDoc = objWord.Documents.Add
   Set objSelect = objWord.Selection
   objSelect.TypeText "Word document created with Automation"
   strPath = GetTempDir & "\test.doc"
   objDoc.SaveAs strPath
   Set objDocItem = Application.CopyFile(strPath, "Inbox")
   objDocItem.Display
   Set objWord = Nothing
End Sub

Returning a MAPI NameSpace object

You can use the GetNameSpace("MAPI") method of the Application object to return the MAPI message store.

In the following example, the GetNameSpace method returns the NameSpace object. The Offline property of the NameSpace object is then used to display a message box indicating whether the user is on line or off line.

Sub CommandButton1_Click()
    Dim MyNameSpace As NameSpace
    Set MyNameSpace = Application.GetNamespace("MAPI")
    If MyNameSpace.Offline Then
        MsgBox "You are offline!", vbInformation
    Else
        MsgBox "You are online!", vbInformation
    End If
End Sub

**Important **  The only data source currently supported is MAPI, which allows access to all Outlook data stored in MAPI. For this reason, the GetNameSpace method must always appear in Outlook as GetNameSpace("MAPI").

Creating Office objects

The Application object has several child objects that are actually members of the Microsoft Office Object Model. For example, the Application object contains member objects for the Office AnswerWizard, Assistant, COMAddIns, and LanguageSettings objects. The following code example uses an animated Assistant to display the LanguageID settings for the Outlook Application object.

'Display the LanguageSettings
Sub DisplayLanguageSettings_Click
    Const msoLanguageIDInstall = 1, msoLanguageIDUI = 2
    Const msoLanguageIDHelp = 3
    Const msoAnimationListensToComputer = 26
    Const msoModeModal = 0, msoButtonSetOK = 1, msoIconTip = 3
    On Error Resume Next
    Dim oa 'As Office.Assistant
    Dim bln 'As Office.Balloon
    strMsg = "The following locale IDs are registered " _
        & "for this application:" & vbCr & "Install Language - " & _
        Application.LanguageSettings.LanguageID(msoLanguageIDInstall) _
        & vbCr & "User Interface Language - " & _
        Application.LanguageSettings.LanguageID(msoLanguageIDUI) _
        & vbCr & "Help Language - " & _
        Application.LanguageSettings.LanguageID(msoLanguageIDHelp)
    Set oa = Application.Assistant
    oa.On = True 'Assistant not available
    If Err Then
        MsgBox strMsg, vbInformation
    Else
        oa.Visible = True
        Set bln = oa.NewBalloon
        bln.Heading = "Language Settings"
        bln.Mode = msoModeModal
        bln.Button = msoButtonSetOK
        bln.Icon = msoIconTip
        bln.Text = strMsg
        bln.Show
        oa.Animation = msoAnimationListensToComputer
    End If
End Sub 

The ability to create a programmatic search using the AdvancedSearch method of the Application object is new to Outlook 2002. AdvancedSearch returns a Search object, which in turn contains a Results object that you can use to iterate over the items contained in that Results object. A Results object is identical to an Items collection object. You use the AdvancedSearch method in conjunction with the AdvancedSearchComplete event for the Application object. When the AdvancedSearchComplete event fires, you'll know that the Search object for your query is available for further processing. Assign a Tag value in your call to AdvancedSearch so that you can identify the correct Search object in the

AdvancedSearchComplete event. See Chapter 9, "Raise Events and Move to the Head of the Class," for additional details on the AdvancedSearchComplete event and Chapter 14, "Creating COM Add-Ins with Visual Basic," for a discussion of the sample Search add-in.

AdvancedSearch takes four arguments, two of which are enigmatically explained in Outlook Visual Basic Help. Here is the syntax for a call to AdvancedSearch:

Set objSearch = objApp.AdvancedSearch(Scope, Filter, SearchSubfolders,
  Tag)

Both the Scope and Filter arguments can be understood in the context of Microsoft Exchange 2000 Web Storage queries. Although you don't have to run against an Exchange 2000 server to use AdvancedSearch, you should consult the Exchange SDK to gain a complete understanding of Web Storage System SQL. The Exchange SDK is available on the Web at http://msdn.microsoft.com/exchange and is also included on this book's companion CD. See the section entitled "Web Storage System SQL."

Fortunately, there are quicker and less painful ways to get up to speed with Filter and Scope syntax. You can use an undocumented Registry key to display a Query Builder page on the Filter dialog box associated with the View Summary dialog box. (See Figure 11-1.) After you use the Query Builder to construct your query, you can then copy the Filter syntax displayed on the SQL page and paste it into your code. Do not attempt to add the Query Builder page Registry setting unless you are familiar with the Microsoft Windows® Registry Editor.

Aa155615.odc_c11612730-01(en-us,office.10).gif

Figure 11-1. The undocumented Query Builder page on the Filter dialog box

To display the Query Builder page on the Filter dialog box

  1. Click Start, point to Run, type Regedit in the Run dialog box, and then click OK to launch the Windows Registry editor.
  2. In the Registry tree, navigate to HKEY_CURRENT_USER\Software\Microsoft\Office\10.0\Outlook.
  3. Select New from the Edit menu, and then select Key from the New submenu.
  4. Type QueryBuilder in the Key edit box. Regedit will suggest New Key #1, but you should replace that key name with QueryBuilder.

To build a filter using the Query Builder page on the Filter dialog box

  1. In Outlook, select Current View from the View menu and then select Customize Current View from the Current View submenu.
  2. Click the Filter button on the View Summary dialog box.
  3. Click the Query Builder page on the Filter dialog box.
  4. Use the Query Builder interface to build your query. When you construct a filter, you actually build a WHERE clause without the WHERE keyword. Notice that you can use the logical AND or logical OR operator to develop the query and move clauses up or down.
  5. Click the SQL page shown in Figure 11-2 on the Filter dialog box, and clear the Edit These Criteria Directly check box. Once you clear the check box, you can copy the query by selecting it and pressing Ctrl+C to copy to the Clipboard.
  6. Because you don't want to modify the view, click Cancel to dismiss the Filter dialog box. Then click Cancel again to dismiss the View Summary dialog box.

Once you have constructed your Filter string, the rest of the process is relatively straightforward. The Scope argument can use either an unqualified folder name such as Inbox, Drafts, Tasks, or a folder path in a Web Storage System SQL Scope clause. SearchSubFolders is Boolean and will work only in a Mailbox or PST store. If you're searching a public folder, you can search only one folder at a time. This is a built-in limitation of the MAPI Public Folder store. As stated previously, you should use the AdvancedSearchComplete event to process the Search object returned by AdvancedSearch. This next code example shows you how to construct a programmatic search and displays the user form shown in Figure 11-3 when the search is complete.

Aa155615.odc_c11612730-02(en-us,office.10).gif

Figure 11-2. Copy a Filter string from the SQL page of the Filter dialog box to provide the Filter argument for the AdvancedSearch method.

Sub ShowSearch()
    Dim olApp As Outlook.Application
    Dim objFolder As MAPIFolder
    Dim objSearch As Search
    Dim strFolderPath As String, strScope As String, strFilter As 
      String
    Set olApp = New Outlook.Application
    'Create a MAPIFolder object for Inbox
    Set objFolder = olApp.GetNamespace("MAPI") _
       .GetDefaultFolder(olFolderInbox)
    'Get the folder path
    strFolderPath = objFolder.FolderPath
    'Build a scope string
    strScope = "SCOPE ('shallow traversal of " _
       & AddQuotes(strFolderPath) & "')"
    'Build a filter string (WHERE clause without the WHERE)
    strFilter = AddQuotes("urn:schemas:mailheader:subject") _
       & " LIKE 'RE:%'"
    'Create the Search object by calling AdvancedSearch
    Set objSearch = _
       olApp.AdvancedSearch(strScope, strFilter, False, "RESearch")
End Sub

Private Sub Application_AdvancedSearchComplete _
    (ByVal SearchObject As Search)
    On Error Resume Next
    Dim objResults As Results
    Dim objItem As Object
    Dim objListItem As Object
    Dim frmAdvancedSearch As New frmSearch
    If SearchObject.Tag = "RESearch" Then
        frmAdvancedSearch.ListView1.ListItems.Clear
        'Create the Results object
        Set objResults = SearchObject.Results
        'Create a reference to first item in Results object
        Set objItem = objResults.GetFirst
        If Not objItem Is Nothing Then
            Do
                'Add item to the ListView control
                Set objListItem = _
                   frmAdvancedSearch.ListView1.ListItems.Add
                With objListItem
                    .Text = objItem.Subject
                    .SubItems(1) = objItem.SenderName
                    .SubItems(2) = objItem.ReceivedTime
                    .SubItems(3) = objItem.Size
                    'Parent is Item container
                    .SubItems(4) = objItem.Parent
                    .SubItems(5) = objItem.EntryID
                End With
                'Reference next item in the Results object
                Set objItem = objResults.GetNext
            Loop Until objItem Is Nothing
        End If
        frmAdvancedSearch.Show
    End If
End Sub

Aa155615.odc_c11612730-03(en-us,office.10).gif

Figure 11-3. Display a custom dialog box that shows the results of a programmatic search in a ListView control.

The NameSpace Object

In Outlook, the NameSpace object represents the MAPI message store. The NameSpace object provides methods for logging on or off Outlook, referencing a default folder, and returning objects directly by ID. In addition, the NameSpace object provides access to a variety of methods and properties that are not normally available with the Application object.

**More Info **  For a complete list and description of the methods, properties, and events for the NameSpace object, see Microsoft Outlook Visual Basic Reference Help.

**Important **  Open the NameSpace object item in the VBScript Samples folder to work directly with this code in Outlook.

NameSpace Object Methods

This section covers the GetDefaultFolder method and the dial method of the NameSpace object.

Returning a default folder

You can use the GetDefaultFolder method of the NameSpace object to access folders in the root folder, also known as the Mailbox. To reference a folder in the Mailbox, you can either specify a numeric value as the argument in the GetDefaultFolder method or copy the olDefaultFolders constants from the Outlook Constants item in the VBScript Samples folder and paste them into your code. The table on the following page lists these numeric values.

The following example uses the GetDefaultFolder method of the NameSpace object to return the Contacts folder and then display it:

Sub CommandButton1_Click
    Set MyFolder = 
      Application.GetNameSpace("MAPI").GetDefaultFolder(10)
    MyFolder.Display
End Sub
Folder Value
Deleted Items 3
Outbox 4
Sent Items 5
Inbox 6
Calendar 9
Contacts 10
Journal 11
Notes 12
Tasks 13
Drafts 16

Dialing a phone number

The Dial method is new to Outlook 2002. If you supply a ContactItem as the argument to the Dial method, you will display the Outlook automatic phone dialer for that contact. The following code example uses the Dial method for the first ContactItem in your Contacts folder:

Sub DialPhone_Click()
    On Error Resume Next
    Dim objContactsFolder, objContactItem
    Const olFolderContacts = 10
    Set objContactsFolder = _
        Application.GetNamespace("MAPI") _
        .GetDefaultFolder(olFolderContacts)
    Set objContactItem = objContactsFolder.Items(1)
    If objContactItem Is Nothing Then
        MsgBox "Could not find a contact to dial." _
            , vbInformation
    Else
        Application.GetNamespace("MAPI").Dial (objContactItem)
    End If 
End Sub

Properties of the NameSpace Object

The NameSpace object provides two properties that you use quite often. These are the CurrentUser and Folders properties.

Returning the name of the current user

You can use the CurrentUser property of the NameSpace object to return the name of the currently logged-on user. This example shows the current user's name in the message box when the CommandButton1 control is clicked:

Sub CommandButton1_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    MsgBox MyNameSpace.CurrentUser
End Sub

Referencing a folder collection

You can use the Folders property of the NameSpace object to reference the collection of folders in the MAPI NameSpace. The following example displays the number of subfolders in the Building Microsoft Outlook 2002 Applications .pst file:

Sub ReferenceAFolderCollection_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    set objFolder = _
        MyNameSpace("Building Microsoft Outlook 2002 Applications")
    Set colFolders = objFolder.Folders
    MsgBox "There are " & colFolders.Count & " subfolders" _
        & vbCr & "in " & objFolder.Name, vbInformation
End Sub

Selecting a folder

You can use the PickFolder method of the NameSpace object to return a MAPIFolder object. The PickFolder method displays a dialog box for the user to select a folder from all available folders in the current profile. The following example displays the Select Folders dialog box and also displays an alert dialog box if the user clicks Cancel. If the user selects a folder, then the folder is displayed in an Explorer window.

Sub PickAFolder_Click()
On Error Resume Next
Set MyNameSpace = Application.GetNameSpace("MAPI")
Set objFolder = MyNameSpace.PickFolder
    If objFolder Is Nothing then
        MsgBox "User Pressed Cancel!", vbInformation
    Else
        objFolder.Display
    End If
End Sub

The Outlook E-Mail Security Update object model guard

If you're using Outlook 2002 or a version of Outlook 2000 or Outlook 98 with the Outlook E-Mail Security Update installed, the code shown in CommandButton1_Click will display a Warning dialog box, as shown in Figure 11-4. Accessing the CurrentUser property causes the Warning dialog box to appear. The object model guard component of the Outlook E-Mail Security Update figures prominently in this chapter. Wherever possible, I will suggest workarounds for blocked object model properties and methods. Remember that developers targeting Exchanger Server users can use the Administrative form in Public Folders to designate selected COM Add-ins as trusted. These trusted COM Add-ins are not subject to the limitations of the object model guard. For details regarding the Outlook E-Mail Security Update and the use of trusted COM Add-ins to customize security restrictions, see Chapter 13.

In order to avoid the Warning dialog box, use the following code to obtain the name of the CurrentUser property:

Function GetCurrentUser()
    Dim objTopFolder As MAPIFolder
    Dim strTopFolder As String
    Dim olApp As Outlook.Application
    Set olApp = CreateObject("Outlook.Application")
    Set objTopFolder = olApp.GetNamespace("MAPI") _
       .GetDefaultFolder(olFolderInbox).Parent
    strTopFolder = objTopFolder.Name
    If InStr(1, strTopFolder, "-") Then
        GetCurrentUser = _
          Trim(Right(strTopFolder, _
          Len(strTopFolder) - InStr(1, strTopFolder, "-")))
    Else
        GetCurrentUser = strTopFolder
    End If
End Function

Aa155615.odc_c11612730-04(en-us,office.10).gif

Figure 11-4. This Warning dialog box appears when you attempt to access the CurrentUser property of the NameSpace object.

The Outlook Window (Explorer Objects)

The Explorer object represents the window in which the contents of a folder are displayed. The Explorers object is the parent collection object for Explorer objects. The following sections cover some of the methods and properties for the Explorer and Explorers objects.

Figure 11-5 illustrates elements of the Outlook user interface viewed from an object model perspective. This illustration is not meant to be all-inclusive; it shows just a few of the objects in the Outlook Object Model that you can manipulate programmatically.

Aa155615.odc_c11612730-05(en-us,office.10).gif

Figure 11-5. Object model components of the Outlook user interface

**More Info **  For a complete list and description of the properties, methods, and events for the Explorer and Explorers objects, see Microsoft Outlook Visual Basic Reference Help.

**Important **  Open the Explorer object item in the VBScript Samples folder to work directly with this code in Outlook.

Explorer Methods

Creating a new Explorer window

Outlook supports an Explorers collection object. You can use the Explorers object to add a new Explorer window for a specific folder. Use the Display method to present the new Explorer window. The following example creates a new Explorer window for the Drafts folder by using the Add method and then shows the new window on the desktop in a normal window state.

Const olNormalWindow = 2
Sub DisplayNewExplorer_Click
    Set myExplorers = Application.Explorers
    Set myFolder = 
      Application.GetNameSpace("MAPI").GetDefaultFolder(16)
    Set myOlExpl = myExplorers.Add(myFolder, 2)
    myOlExpl.Display
    myOlExpl.WindowState = olNormalWindow
End Sub

Explorer Properties

Returning the active folder

You can use the CurrentFolder property of the Explorer object to return the active folder in the Outlook window. The following example shows the name of the active folder in the message box when the DisplayTheCurrentFolder control is clicked:

Sub DisplayTheCurrentFolder_Click
    Set myExplorer = Application.ActiveExplorer
    MsgBox "The current folder in the Explorer is: " _
        & myExplorer.CurrentFolder.Name, vbInformation
End Sub

Obtaining the current view for the active Explorer

You can use the CurrentView property of the Explorer object to return or set the current view for the Active Explorer window. The example on the following page displays the name of the current view for the Active Explorer window.

Sub DisplayTheExplorerView_Click
    Set myExplorer = Application.ActiveExplorer
    MsgBox "The current Explorer view is: " & vbCr _
        & myExplorer.CurrentView, vbInformation
End Sub

Determining which items are selected in the Explorer

The Selection collection object lets you know which items are selected in the Explorer window. The Selection object, in turn, contains an Items collection that lets you iterate over selected items. If you are writing VBA code, you can respond to the SelectionChange event of the Explorer object. The following example displays the number of selected items in the Active Explorer and then asks whether the user wants to display the items:

Sub DisplaySelectedItems_Click
    DisplayNewExplorer_Click
    Set mySelection = Application.ActiveExplorer.Selection
    MsgBox "The number of selected items in the Explorer is " _
        & mySelection.Count, vbInformation
    If MsgBox ("Display selected items?", vbYesNo+vbQuestion) = vbNo 
      Then
        Exit Sub
    End If
    For i = 1 to mySelection.Count
        Set myItem = mySelection.Item(i)
        myItem.Display
    Next
End Sub

The Panes Collection Object

The Panes collection object is a property object of the Explorer object. The Panes collection object contains the three panes of the Outlook Explorer window, as shown in Figure 11-6. These are the Outlook Bar pane, the Folder List pane, and the Preview pane.

You can create an instance of an OutlookBarPane object from the Panes collection only. The Preview and Folder List panes are not accessible from the Outlook Object Model. When you navigate an Outlook Bar's groups and shortcuts in code, you start with the Panes collection object, as demonstrated in the following code example:

Dim OlBarPane As Outlook.OutlookBarPane
Dim OlExplorer As Outlook.Explorer
Set OlExplorer = Application.ActiveExplorer
Set OlBarPane = OlExplorer.Panes("OutlookBar")
'Make the Outlook Bar visible if it's hidden
If OlBarPane.Visible = False Then
    OlBarPane.Visible = True
End If
MsgBox "The Current Outlook Bar Group is " _
  & OlBarPane.CurrentGroup, vbInformation

Aa155615.odc_c11612730-06(en-us,office.10).gif

Figure 11-6. Three Explorer panes comprise the Panes collection object.

Determining Whether a Pane is Visible

You can determine whether an individual pane is visible by using the IsPaneVisible method of the Explorer object. To make a pane visible, you use the ShowPane method. The following VBScript code makes the Folder List pane visible:

Sub ShowFolderList
    Const olFolderList = 2
    Set objExpl = Application.ActiveExplorer
    If Not(objExpl.IsPaneVisible(olFolderList)) Then
        objExpl.ShowPane olFolderList, True
    End If
End Sub

**Note **  You cannot size panes programmatically in the Explorer window in Outlook.

The OutlookBarPane Object

The OutlookBarPane object is the only object you can instantiate from the Panes collection object. It represents the Outlook Bar as well as its groups and shortcuts. Generally, you'll create a reference to the OutlookBarPane object as a means to access its dependent child objects that represent Outlook Bar groups and shortcuts. You can use the CurrentGroup property of the OutlookBarPane object to set or get the current group on the Outlook Bar. The OutlookBarPane object supports two important events: BeforeNavigate and BeforeGroupSwitch. These events inform you when a user is navigating to a shortcut or a group, respectively. For additional information on writing event procedures as well as the events supported by the OutlookBarPane, OutlookBarGroups, and OutlookBarShortcuts objects, see Chapter 9.

The OutlookBarStorage Object

The OutlookBarStorage object is an accessor object in the Outlook object hierarchy and has no methods or events of its own. OutlookBarStorage is used to access the OutlookBarGroups collection object through its Groups property. You can access the OutlookBarStorage object by using the Contents property of the OutlookBarPane object. The following VBA code demonstrates the use of the Contents and Groups property objects:

Dim OlBarPane As Outlook.OutlookBarPane
Dim OlBarStorage As Outlook.OutlookBarStorage
Dim OlBarGroups As Outlook.OutlookBarGroups
Dim OlExplorer As Outlook.Explorer
Set OlExplorer = Application.ActiveExplorer
Set OlBarPane = OlExplorer.Panes("OutlookBar")
Set OlBarStorage = OlBarPane.Contents
Set OlBarGroups = OlBarStorage.Groups
'This code is more efficient
'Set OlBarGroups = OlBarPane.Contents.Groups
MsgBox "There are " & OlBarGroups.Count _
  & " groups on your Outlook Bar.", vbInformation

The OutlookBarGroups Collection Object

The OutlookBarGroups collection object is one of two critical collection objects used to program the Outlook Bar. Using the Groups object, you can add, modify, or delete groups on the Outlook Bar. The OutlookBarGroups object also supports three events that provide an additional level of programmatic control over Outlook Bar groups: GroupAdd, BeforeGroupAdd, and BeforeGroupRemove. The following example creates an Outlook Bar group named Web Links and positions it as the last group on the Outlook Bar:

Dim OlBarGroups As Outlook.OutlookBarGroups
Dim OlBarGroup As Outlook.OutlookBarGroup
Set OlBarGroups = _
  Application.ActiveExplorer.Panes("OutlookBar").Contents.Groups
Set OlBarGroup = OlBarGroups.Add(Name:="Web Links", _
  Index:=OlBarGroups.Count + 1)

**Note **  The Add method just shown uses named arguments to pass the name and index arguments to the Add method of the OutlookBarGroups object. You can list named arguments in any order. A named argument consists of the name of the argument, followed by a colon and an equal sign (:=), followed by the value assigned to the argument. You can also use expressions, and the value of the expression will be assigned to the argument.

The OutlookBarGroup Object

The OutlookBarGroup object represents a group on the Outlook Bar. You can manipulate the properties of the OutlookBarGroup object using its Name and ViewType properties. The ViewType property controls whether the shortcuts in the group display with a large or small icon. Use the Item property to access an existing member of an OutlookBarGroups collection object. The following example renames the Outlook Bar group named Web Links that we created in the previous example and changes the shortcuts to small icons. This enables the user to see more icons in the group before having to use the scroll bar to view other shortcuts.

Dim OlBarGroups As Outlook.OutlookBarGroups
Dim OlBarGroup As Outlook.OutlookBarGroup
Set OlBarGroups = _
  Application.ActiveExplorer.Panes("OutlookBar").Contents.Groups
Set OlBarGroup = OlBarGroups.Items("Web Links")
With OlBarGroup
    .Name = "Outlook Web Links"
    .ViewType = olSmallIcon
End With

The OutlookBarShortcuts Collection Object

OutlookBarShortcuts is a property collection object for the OutlookBarGroups object. You use this collection object to add, modify, or remove shortcuts from an Outlook Bar group. Like the OutlookBarGroups collection object, OutlookBarShortcuts supports three events you can use when you write event procedures to be executed when an Outlook shortcut has been added or removed. These events are ShortcutAdd, BeforeShortcutAdd, and BeforeShortcutRemove.

The OutlookBarShortcut Object

The OutlookBarShortcut object represents a shortcut on the Outlook Bar. A shortcut in Outlook 2000 or Outlook 2002 can launch an executable file on a local or network drive, navigate to a URL, or navigate to an Outlook folder in the folder hierarchy. The following table lists some of the common shortcuts used in Outlook 2000 and Outlook 2002.

Shortcut Function Target Property Example
Navigate to Outlook folder MAPIFolder object
objNS.GetDefaultFolder(olFolderDrafts) OlBarShortcuts.Add oFolder, "Drafts"
Open a file system file String file URL specification
strTarget = file:\\c:\my 
  documents\foo.xls
OlBarShortcuts.Add strTarget, "My 
  File"
Open a file system folder String folder path specification
strTarget = "c:\my documents" 
  OlBarShortcuts.Add strTarget, "My 
  Documents"
Open a Web page String URL
strTarget = "http://www.slipstick.com" 
  OlBarShortcuts.Add strTarget, 
  "Slipstick"

The Target property of OutlookBarShortcut determines what action occurs when a user clicks a shortcut on the Outlook Bar. Oddly enough, the Target property is read-only; when you set the Target property by adding a shortcut, you must remove the shortcut and add it again if you want to change the property.

**Note **  If you use an http URL as the target of a shortcut, Outlook will open the Web page as a Web View in the Outlook Explorer window. If you want to open the Web page in a separate window, right-click the shortcut in Outlook and select Open In New Window from the shortcut menu. In Outlook 2000, this action will open the URL in a new browser window. In Outlook 2002, this action will open the URL in a new Outlook Explorer window.

OutlookBarShortcut supports the new SetIcon method for Outlook 2002. Use SetIcon to set the icon for an OutlookBarShortcut object.

The CommandBars Collection Object

The ability to program the Outlook Bar gives you a significant level of control over the Outlook user interface. Using the OutlookBarGroups and OutlookBarShortcuts events, you can prevent a user from removing an Outlook Bar group or shortcut that is essential to your application. You can also dynamically add Outlook Bar groups and shortcuts. You don't have the same flexibility, however, with Outlook Bar objects as you do with all the objects belonging to Office command bars. CommandBar and Assistant objects are actually members of the Office Object Model. CommandBar objects give you the opportunity to customize Outlook in a way that was impossible in Outlook 97 and Outlook 98. That said, the following discussion gives an overview of using command bars in Outlook. How you call CommandBar objects in Outlook differs somewhat from how you call them in other Office applications.

**Note **  If you are writing a COM Add-in, you must explicitly add a reference to the Microsoft Office 9.0 Object Library or Microsoft Office 10.0 Object Library using the appropriate command in your development tool. If you are using Outlook VBA to write code in the VBAProject.otm file, Outlook automatically creates a reference to the Microsoft Office 10.0 Object Library.

Overview of Command Bars

In the Outlook Object Model, both the Explorer and Inspector objects contain a CommandBars property object. The CommandBars object for Inspector and Explorer controls all Outlook toolbars, menu bars, and shortcut menus. The CommandBar object and its children contain the following items:

  • Menu bars, toolbars, and shortcut menus
  • Menus on menu bars and toolbars
  • Submenus on menus, submenus, and shortcut menus

You can modify any built-in menu bar or toolbar, and you can create and modify custom toolbars, menu bars, and shortcut menus to deliver with your Outlook VBA project or COM Add-in application. Use command bar customization to present the features of your application as individual buttons on toolbars or as groups of command names on menus. Because both toolbars and menus are command bars, you can use the same kind of controls on them.

Custom command bars differ somewhat from built-in command bars because they can be deleted from the Outlook environment. Built-in command bars can be modified by the user or by program code. However, built-in command bars can be restored to their original state and default behavior by using the Reset command button on the Toolbars page of the Customize dialog box.

The following table shows the built-in command bars in Outlook.

Object Built-In Command Bar
Explorer Menu Bar
  Standard
  Advanced
  Remote (Outlook 2000 only)
  Web
  Clipboard (Outlook 2000 only)
Inspector Menu Bar
  Standard
  Formatting
  Form Design
  Clipboard (Outlook 2000 only)

Be aware that command bars are defined as either docked or, in the case of a floating command bar or menu bar, undocked. Outlook features four command bar docks—one at the left, right, top, and bottom of the Outlook window.

Outlook CommandBarButton objects represent buttons and menu items. The pop-up controls that display menus and submenus are known as CommandBarPopup objects. Both the menu and the submenu are unique CommandBar objects with their own sets of controls. In addition to CommandBarButton and CommandBarPopup objects, the CommandBarControls object can contain CommandBarComboBox objects. CommandBarComboBox objects assume a variety of different types: edit box, drop-down list box, or drop-down combo box. Like the List Box control on Outlook forms, the CommandBarComboBox object supports both an AddItem method to add items to the control and a ListIndex property to retrieve the selection index.

Exploring the CommandBars Collection

One way to learn more about the CommandBars object is to write code that maps the existing built-in and custom Outlook command bars. Because Outlook supports command bars for both the Explorer and Inspector windows, the following function requires a class argument that indicates whether the Inspector or Explorer command bars and controls should be output to the Debug window.

PrintAllCBarInfo can be found in the basCommandBars module in VBA Samples.zip in the VBA Samples folder.

To use the code in the VBA Samples folder

  1. Using Windows Explorer, expand the Building Microsoft Outlook 2002 Applications folder. Then expand the 4. Beyond the Basics folder, and then expand the Visual Basic For Applications folder, followed by the VBA Samples folder.
  2. The code, class, and user form modules for VBAProject.otm are in VBA Samples.zip in the VBA Samples folder. You can extract these items from VBA Samples.zip by using a Zip utility program such as WinZip, which is availble at http://www.winzip.com.
  3. You can also replace your current VBAProject.otm file with the VBAProject.otm installed by the setup program on the companion CD.

To run the PrintAllCBarInfo procedure

  1. Open the Visual Basic Editor by pressing Alt+F11.
  2. Extract basCommandBars from VBA Samples.zip in the VBA Samples folder to a file system folder.
  3. Select Import File on the File menu to import basCommandBars into your Outlook VBAProject.otm.
  4. Press Ctrl+G to open the Debug window.
  5. Type ?PrintAllCBarInfo(olExplorer), and press Enter. Information on all command bars and controls in the CommandBars collection will display in the Debug window.
Function PrintAllCBarInfo(intClass As Integer)
    'This procedure prints (to the Debug window)
    'information about each command bar in the
    'active Explorer or Inspector window.
    'Use OlExplorer or OlInspector for intClass argument
    Dim cbrBar As Office.CommandBar
    Dim colCB As Office.CommandBars
    On Error Resume Next
    If intClass = OlExplorer Then
        Set colCB = Application.ActiveExplorer.CommandBars
        If Err Then
            Debug.Print "No Active Explorer found!"
            Exit Function
        End If
    Else
        Set colCB = Application.ActiveInspector.CommandBars
        If Err Then
            Debug.Print "No Active Inspector found!"
            Exit Function
        End If
    End If
    For Each cbrBar In colCB
        CBPrintCBarInfo cbrBar.Name, intClass
    Next cbrBar
End Function

The following function is a helper function for the CBPrintAllCBarInfo function just shown. This function calls two other functions that enumerate the types of command bars and command bar controls. See the code in the basCommandBars module for a complete listing.

Function CBPrintCBarInfo(strCBarName As String, intClass As Integer) _
  As Variant
    'This procedure prints (to the Debug window) information
    'about the command bar specified in the strCBarName argument
    'and information about each control on that command bar.
    'Use olExplorer or olInspector for intClass argument
    Dim cbrBar                      As CommandBar
    Dim ctlCBarControl              As CommandBarControl
    Const ERR_INVALID_CMDBARNAME    As Long = 5
    On Error GoTo CBPrintCBarInfo_Err

    If intClass = OlExplorer Then
        Set cbrBar = 
          Application.ActiveExplorer.CommandBars(strCBarName)
    Else
        Set cbrBar = 
          Application.ActiveInspector.CommandBars(strCBarName)
    End If

    Debug.Print "CommandBar: " & cbrBar.Name & vbTab & "(" _
        & CBGetCBType(cbrBar) & ")" & vbTab & "(" _
        & IIf(cbrBar.BuiltIn, "Built-in", "Custom") & ")"
    For Each ctlCBarControl In cbrBar.Controls
        Debug.Print vbTab & ctlCBarControl.Caption & vbTab & "(" _
            & CBGetCBCtlType(ctlCBarControl) & ")"
    Next ctlCBarControl
CBPrintCBarInfo_End:
    Exit Function
CBPrintCBarInfo_Err:
    Select Case Err.Number
        Case ERR_INVALID_CMDBARNAME
            CBPrintCBarInfo = "'" & strCBarName & _
                "' is not a valid command bar name!"
        Case Else
            CBPrintCBarInfo = "Error: " & Err.Number _
                & " - " & Err.Description
    End Select
    Resume CBPrintCBarInfo_End
End Function

Listed next you'll find the output of CBPrintCBarInfo as it appears in the Debug window. This excerpt shows all the controls on the Outlook Advanced toolbar.

CommandBar: Advanced    (Toolbar)   (Built-in)
    Outloo&k Today  (Button)
    &Back   (Button)
    &Forward    (Button)
    &Up One Level   (Button)
    Fold&er List    (Button)
    Preview Pa&ne   (Button)
    Print Pre&view  (Button)
    &Undo   (Button)
    Ru&les Wizard...    (Button)
    Current &View   (Combobox)
    Group &By Box   (Button)
    Field &Chooser  (Button)
    Auto&Preview    (Button)

Using Images on Command Bar Buttons

Once you have explored the Outlook command bars and their controls, take a look at the images used on these buttons. If you plan to write code to create your own custom command bars, you need to find a source for icons that will appear on the buttons. You can use the FindControl,CopyFace, and PasteFace methods to copy and paste images from a built-in button to custom buttons you've created. You can also supply a FaceID value for your custom command bar button that corresponds to the FaceID for a built-in icon. The following procedure creates a temporary custom toolbar that displays built-in Office icons, as shown in Figure 11-7 (on page 443). If you hold your mouse pointer over the button, a tooltip will display the FaceID property.

To run the CBShowButtonFaceIDs procedure

  1. Open the Visual Basic Editor by pressing Alt+F11.
  2. Drag basCommandBars from the VBA Samples folder to a file system folder such as C:\My Documents.
  3. Select Import File on the File menu to import basCommandBars into your Outlook VBAProject.otm.
  4. Press Ctrl+G to open the Debug window.
  5. Type ?CBShowButtonFaceIDs(0, 299, olExplorer), and press Enter.
  6. Press Alt+F11 to return to the Outlook application window. You should see the ShowFaceIDs toolbar displayed over the Explorer window.
Function CBShowButtonFaceIDs(lngIDStart As Long, _
        lngIDStop As Long, intClass As Integer)

    'This procedure creates a toolbar with buttons that display the
    'images associated with the values starting at lngIDStart and
    'ending at lngIDStop
    'Use olExplorer or olInspector for intClass argument
    Dim cbrNewToolbar   As CommandBar
    Dim cmdNewButton    As CommandBarButton
    Dim intCntr         As Integer

    'If the ShowFaceIds toolbar exists, delete it
    On Error Resume Next
    If intClass = OlExplorer Then
        'Delete the ShowFaceIds toolbar
        Application.ActiveExplorer.CommandBars("ShowFaceIds").Delete
        'Create a new toolbar
        Set cbrNewToolbar = 
          Application.ActiveExplorer.CommandBars.Add _
            (Name:="ShowFaceIds", Temporary:=True)
    Else
        'Delete the ShowFaceIds toolbar
        Application.ActiveInspector.CommandBars("ShowFaceIds").Delete

        'Create a new toolbar
        Set cbrNewToolbar = 
          Application.ActiveInspector.CommandBars.Add _
            (Name:="ShowFaceIds", Temporary:=True)
    End If

    'Create a new button with an image matching the FaceID property 
      value
    'indicated by intCntr
    For intCntr = lngIDStart To lngIDStop
        Set cmdNewButton = _
          cbrNewToolbar.Controls.Add(Type:=msoControlButton)
        With cmdNewButton
            'Setting the FaceID property value specifies the appearance
            'but not the functionality of the button
            .FaceId = intCntr
            .Style = msoButtonIcon
            .Visible = True
            .TooltipText = "FaceId = " & intCntr
        End With
    Next intCntr

    'Show the images on the toolbar
    With cbrNewToolbar
        .Width = 600
        .Left = 100
        .Top = 100
        .Visible = True
    End With

End Function

Aa155615.odc_c11612730-07(en-us,office.10).gif

Figure 11-7. The ShowFaceIds toolbar provides a palette of images to use for custom buttons.

Use the ShowFaceIDs toolbar to provide icon images for your custom toolbar buttons. Place the cursor over the desired command button to learn its FaceID property. You can copy the code for the cmdNewButton object shown a moment ago and paste it into the code that your own button creates. Just substitute the actual value for the FaceID icon that you need for the intCntr variable.

Adding a Command Bar to the Collection

Use the Add method to add a command bar to either the Inspector or the Explorer CommandBars collection. If you are using Visual Basic rather than VBScript, you can use named arguments when you call the Add method of the CommandBars collection object to add a command bar. The following example adds the Items command bar to the Explorer CommandBars collection:

Dim cbrNewToolbar As CommandBar
Set cbrNewToolbar = Application.ActiveExplorer.CommandBars.Add _
            (Name:="Items", Position:=msoBarTop, Temporary:=False)

In VBScript, all variables are declared as Variants and named arguments are illegal. Here is a statement that adds an Inspector command bar:

Set objCommandBar= Item.GetInspector.CommandBars.Add _
            ("Command Bar Example", 1, False, True)

The Position property determines whether the toolbar will be docked in the Explorer or the Inspector window or displayed as a floating toolbar. If you supply the msoBarPopUp value for the Position argument, you will create a shortcut menu rather than a menu bar or toolbar. The following table shows the possible values for the Position property.

Constant Description
msoBarLeft=0, msoBarTop=1, msoBarRight=2, msoBarBottom=3 Indicates the left, top, right, and bottom coordinates of the new command bar
msoBarFloating=4 Indicates that the new command bar won't be docked
msoBarPopup=5 Indicates that the new command bar will be a shortcut menu

The Temporary property indicates whether the command bar will be deleted when the Outlook application or the Inspector window closes. Notice that the VBScript Command Bar Example toolbar is temporary; it appears only for a specific custom form. Generally, you don't want to create persistent Inspector toolbars.

Note   Once you have added the command bar to the CommandBars collection, you can set additional properties that determine the command bar's appearance and behavior. For example, the Type property determines whether the CommandBar object behaves as a menu bar, toolbar, or shortcut menu.

Retrieving an Existing Command Bar

To retrieve an existing built-in or custom command bar, use the Items property with either an index value or the name of the command bar. Because the Items property is the default property of the CommandBars collection object, you don't actually have to use the Items property to retrieve a command bar from a collection. The following two statements are equivalent:

Set cbrItems = Application.ActiveExplorer.CommandBars.Items("Items")
Set cbrItems = Application.ActiveExplorer.CommandBars("Items")

Deleting a Command Bar

Use the Delete method to delete a custom command bar from the CommandBars collection. You cannot delete a built-in command bar with the Delete method. The Delete method is actually a CommandBar method, not a CommandBars method. The following function deletes a command bar and returns True if the command bar was successfully deleted:

Function CBDeleteCommandBar(strCBarName As String) As Boolean
    On Error Resume Next
    Application.ActiveExplorer.CommandBars(strCBarName).Delete
    If Err = 0 Then
        CBDeleteCommandBar = True
    End If
End Function

Using the OnUpdate Event

The CommandBars collection supports an OnUpdate event that fires whenever a command bar is changed. For additional information regarding Visual Basic events, the WithEvents keyword, and event procedures, see Chapter 9. The event is triggered by any change to a command, or by the state of a bar or command bar control. These changes can result from pressing a button, by changing text, or by selecting a cell. Because a large number of OnUpdate events can occur during normal usage, you should be very cautious when working with this event. I strongly recommend that you use this event primarily for checking that a custom command bar has been added or removed by an Outlook COM Add-in. To see how many times this event can fire, add the following code to VBAProject.otm. A statement appears in the Debug window every time the OnUpdate event fires.

'Place in Declarations of ThisOutlookSession
Dim WithEvents colCB As CommandBars

Private Sub Application_Startup()
    Set colCB = Application.ActiveExplorer.CommandBars
End Sub

Private Sub colCB_OnUpdate()
    Debug.Print "CommandBars OnUpdate"
End Sub

The CommandBar Object

The CommandBar object represents a command bar—either built-in or custom—for either the Outlook Explorer or Inspector window. You can modify a built-in command bar through the Customize dialog box or through program code. If you are building a custom Outlook application or creating a COM Add-in, you should consider providing a custom command bar or modifying the menus on the Outlook menu bar for your COM Add-in. Once you have created a command bar object programmatically, you should add controls to the command bar and program them to respond to events such as Click or Change.

Properties of the CommandBar Object

The following table lists some important properties of the CommandBar object. For additional information on CommandBar object properties, see Microsoft Outlook Visual Basic Reference Help.

Property Description
AdaptiveMenus Determines whether an individual command bar displays adaptive menus. This property can be True or False.
Enabled Determines whether the command bar can be modified with the Customize dialog box. If the Enabled property is False, you cannot set the Visible property to True.
Position Returns or sets the position of the command bar.
Type Determines the type of command bar—menu bar, toolbar, or shortcut menu.
Visible Determines whether the command bar is visible in the Explorer or Inspector window. This property can be True or False.

Methods of the CommandBar Object

The methods listed in the following table operate on the CommandBar object. For additional information on methods for the CommandBar object, see Microsoft Office Visual Basic Reference Help.

Method Description
Delete Deletes a custom command bar.
FindControl Finds a control on a command bar that meets specified criteria. You can search by control type, ID, or tag property based on whether a control is visible or on a submenu.
Reset Resets a built-in command bar to its default configuration. If you have customized a built-in command bar, those customizations are removed when you call this method.
ShowPopup Shows the command bar as a pop-up menu at specified coordinates or at the current cursor location.

The ShowPopup method will work only for a command bar that has been added as a shortcut menu to the CommandBars collection. You cannot cause a built-in or custom toolbar to appear suddenly as a pop-up menu. The Outlook Inspector has a limited capacity to display shortcut menus because a MouseUp event is not supported using the current control container for Outlook custom forms. If you are utilizing UserForms in your VBA or COM Add-in project, use the MouseUp event of intrinsic and third-party ActiveX controls to build event procedures that display Outlook shortcut menus. The following procedure displays a pop-up menu at the current cursor location in the Explorer window:

Sub ExplorerPopUp()
    Dim CBCopyandPasteMenu As Office.CommandBar
    Set CBCopyandPasteMenu = 
     Application.ActiveExplorer.CommandBars.Add _
        (Name:="Custom", Position:=msoBarPopup, Temporary:=True)
    Set Copy = CBCopyandPasteMenu.Controls.Add
    With Copy
        .FaceId = Application.ActiveExplorer.CommandBars _
            ("Menu Bar").Controls("Edit").Controls("Copy").ID
        .Caption = "Copy the selection"
    End With
    Set Paste = CBCopyandPasteMenu.Controls.Add
    With Paste
        .FaceId = Application.ActiveExplorer.CommandBars _
            ("Menu Bar").Controls("Edit").Controls("Paste").ID
        .Caption = "Paste from the Clipboard"
    End With
    CBCopyandPasteMenu.ShowPopup
End Sub

The next procedure uses the MouseUp event to display the Data Helper shortcut menu when the right mouse click occurs over the lstSync control on a UserForm:

Private Sub lstSync_MouseUp _
   (ByVal Button As Integer, ByVal Shift As Integer, _
    ByVal X As Single, ByVal Y As Single)
On Error Resume Next
Dim cbrShortcut As CommandBar
Select Case Button
    Case vbKeyLButton 'Left
    Case vbKeyRButton 'Right
        Set cbrShortcut = _
          Application.ActiveExplorer.CommandBars("Data Helper")
        cbrShortcut.Visible = True

        cbrShortcut.ShowPopup X, Y
End Select
End Sub

Protecting a Command Bar from User Modification

How do you protect a custom command bar you've developed from user modification? A user can modify your command bar either through the user interface or through program code. To prevent changes to your custom command bar, you can set the Enabled property to False to make the command bar invisible in the list of Outlook command bars for either the Explorer or Inspector window. Once the Enabled property is set to False, users cannot modify your custom command bar because they will not be able to see the command bar name in the Toolbars list. You must reset the Enabled property to True before you can use the Visible property to display the command bar. However, the Enabled property is not the most secure means of protecting your custom command bar. The following procedure can prevent a user from using the Customize dialog box to alter your custom command bar. The code disables the Customize command on the Tools menu and the Toolbars list on the View menu.

Sub AllowExplorerCBCustomization(blnAllowEnabled As Boolean)
    'This procedure allows or prevents access to the
    'command bar's Customize dialog box according to the
    'value of the blnAllowEnabled argument.
    Dim colCB As CommandBars
    Set colCB = Application.ActiveExplorer.CommandBars
    colCB("Tools").Controls("Customize...").Enabled = blnAllowEnabled
    colCB("Toolbar List").Enabled = blnAllowEnabled
End Sub

The CommandBarControls Collection Object

CommandBarControls is a collection object that represents all the controls on a command bar. You use the Controls property of a CommandBar object to refer to a control on a command bar. The Controls property is a CommandBarControls collection. If the control is of the type msoControlPopup, it also will have a Controls collection representing each control on the pop-up menu. Pop-up menu controls represent menus and submenus and can be nested several layers deep, as shown in the second example in this section.

In the following example, the code returns a reference to the New button on the Standard toolbar and displays the type of the control in a message box:

Dim ctlCBarControl As CommandBarControl
Set ctlCBarControl = Application.ActiveExplorer.CommandBars _
    ("Standard").Controls("New")
MsgBox "The type of " & ctlCBarControl.Caption _
    & " is " & CBGetCBCtlType(ctlCBarControl), vbInformation

Here, the code returns a reference to the Macros control on the Macro pop-up menu located on the Tools menu on the menu bar for the Explorer window:

Dim ctlCBarControl As CommandBarControl
Set ctlCBarControl = 
  Application.ActiveExplorer.CommandBars("Menu Bar") _
    .Controls("Tools").Controls("Macro").Controls("Macros...")

Because each pop-up menu control is actually a CommandBar object, you can also refer to it directly as a member of the CommandBars collection. For example, the following line of code returns a reference to the same control as the previous example did:

Set ctlCBarControl = Application.ActiveExplorer.CommandBars("Macro") _
    .Controls("Macros...")

Once you have a reference to a control on a command bar, you can access all available properties and methods of that control.

Note   When you refer to a command bar control by using the control's Caption property, you must specify the caption exactly as it appears on the menu. For example, in the previous code sample, the reference to the control caption "Macros. . ." requires the ellipsis (. . .) in order to match the way the caption appears on the menu. However, you do not have to include the ampersand (&) that is returned in the control's Caption property when you refer to the control. Controls("Macros . . .") is equivalent to Controls("&Macros . . .") in the previous example.

Use the Count property of the CommandBarControls collection to return the number of controls in the collection object. To add controls to the collection, use the Add method. The Item property is the default property of the CommandBarControls collection object. For this reason, you do not have to use the Item property to access individual controls in the collection if you are writing Visual Basic or VBA code. Controls("Macros...") is the equivalent of Controls.Item("Macros..."). However, if you are writing VBScript code, you must use the Item property to access individual controls in the collection.

The CommandBarControl Object

The CommandBarControl object is the child object of the CommandBarControls object, and it represents a control on a built-in or custom command bar. If you want to refer to a control on a built-in command bar, you should dimension the control variable as a CommandBarControl object. If you want to instantiate an object on a custom command bar, use the CommandBarButton, CommandBarComboBox, or CommandBarPopup object for your item declaration in Visual Basic. If you are using VBScript in an Outlook form, the type of the object is immaterial because all objects are Variants by default.

Note   If you do declare a control object as a CommandBarControl, you can still use the properties and methods of the CommandBarButton, CommandBarComboBox, and CommandBarPopup objects with it. However, dimensioning the control as the correct variable type is the preferred approach. You cannot use the read-only Type property to change the type of an existing custom control. If you want to change the control type, you must delete the control and then add it with the correct type argument in the Add method of the CommandBarControls object.

Adding Custom Command Bar Controls

The CommandBarControl object allows you to modify built-in controls or to add new controls on a custom command bar. Additionally, you can set the properties of the control to determine how the control will appear or what procedure will run when the user clicks the command button or selects a menu item. The difference between CommandBarControl objects is clearly demonstrated in the following code sample for a command bar named Testing. The Testing command bar, shown in Figure 11-8, uses every type of control available for a custom command bar.

Aa155615.odc_c11612730-08(en-us,office.10).gif

Figure 11-8. The Testing command bar

The code required to create Testing is relatively straightforward. It's presented in sections so that you can clearly understand each step of the coding process. The first order of business is to instantiate a CommandBar object so that controls can be added to the command bar's CommandBarControls collection. The next line attempts to instantiate a Testing CommandBar object from theExplorer's CommandBars collection. If Testing already exists and no error occurs, the existing toolbar is deleted before the command bar is added.

Sub CBTestingDemo()
    Dim cbTesting As CommandBar
    Dim ctlCBarButton As CommandBarButton
    Dim ctlCBarCombo As CommandBarComboBox
    Dim ctlCBarPopup As CommandBarPopup
    On Error Resume Next
    Set cbTesting = Application.ActiveExplorer.CommandBars("Testing")
    If Err = 0 Then
        cbTesting.Delete
    End If
    Set cbTesting = Application.ActiveExplorer.CommandBars _
        .Add(Name:="Testing", Position:=msoBarTop)

Notice that we've added a position argument to the Add method in order to place the command bar in the top dock. Now we're ready to add controls to the command bar. These additional controls don't actually do anything when clicked. Four different types of controls will be added to Testing. The first is a standard button that's typical of the controls on toolbars. We've assigned the caption Color to this button and an icon that corresponds to the built-in FaceID 2167, the icon for the color palette. In order for both the icon and the caption to appear, you must set the button's style to msoButtonIconAndCaption. If you are using a built-in FaceID to provide an icon for a custom button, you must set the button's Visible property to True or the icon will not appear, even though the new button appears on the toolbar.

    Set ctlCBarButton = cbTesting.Controls.Add(Type:=msoControlButton)
    With ctlCBarButton
        .Caption = "Color"
        .FaceId = 2167
        .Style = msoButtonIconAndCaption
        .Visible = True
        .TooltipText = "Test color button"
    End With

The next control to add to Testing is an Edit box control. Edit box controls are equivalent to edit boxes on an Outlook form. A separate object type does not exist for edit controls. Edit box controls are actually CommandBarComboBox objects. Their Type property is msoEditBox. Edit box and List box controls can show a label before the control if their Style property is set to msoComboLabel. The following code adds an Edit box control to Testing and sets its Text property to Red:

    Set ctlCBarCombo = cbTesting.Controls.Add(Type:=msoControlEdit)
    With ctlCBarCombo

        .Caption = "Color: "
        .Text = "Red"
        .Style = msoComboLabel
        .TooltipText = "Test Edit box"
    End With

The ComboBox control uses many of the same properties and methods as the MSForms combo box that you're familiar with from Outlook forms. You can use the AddItem method to add items to the list and the ListIndex property to set or return the selected item in the list. Like the Edit box control, this combo box uses a caption to identify the value being selected by the user.

    Set ctlCBarCombo = cbTesting.Controls.Add(Type:=msoControlComboBox)
    With ctlCBarCombo
        .AddItem "Red"
        .AddItem "Green"
        .AddItem "Blue"
        .ListIndex = 1
        .Caption = "Test Combo box"
    End With

Finally we'll add a Popup control to Testing and make the toolbar visible. Remember that every Popup control contains a Command Bar object and a corresponding controls collection. If you want to add items to the Popup control, use the Add method for the Controls property object of the CommandBarPopup object. The following code adds three button controls to the Popup control. If we added these controls as Popup controls rather than button controls, we would have submenus that could contain additional submenus or button controls.

    Set ctlCBarPopup = cbTesting.Controls.Add(Type:=msoControlPopup)
    Set ctlCBarControl = 
      ctlCBarPopup.Controls.Add(Type:=msoControlButton)
    ctlCBarControl.Caption = "Red"
    Set ctlCBarControl = 
      ctlCBarPopup.Controls.Add(Type:=msoControlButton)
    ctlCBarControl.Caption = "Green"
    Set ctlCBarControl = 
      ctlCBarPopup.Controls.Add(Type:=msoControlButton)
    ctlCBarControl.Caption = "Blue"
    With ctlCBarPopup
        .Caption = "Test Popup"
    End With
    cbTesting.Visible = True
End Sub

**Note **  The last statement in the previous code listing makes the new custom command bar visible. Unless you set the Visible property of your custom command bar, you will not be able to see the new command bar in the Outlook Explorer or Inspector window.

Running a Procedure for a Control

Adding controls to your custom toolbar is not very useful unless they help the user perform an action. To run a procedure when a user clicks a control button or a combo box changes, you can set the OnAction property to refer to a Sub procedure or Function procedure in your project. If you are creating a custom command bar in an Outlook form using VBScript, using the OnAction property is the only way you can run a procedure for a control. If you are creating a COM Add-in, you also have the option to declare the object variable for the control using the WithEvents keyword and run an event procedure when the control's Click event (CommandBarButton) or Change event (CommandBarComboBox) fires.

The following code from the Items toolbar example will cause the LaunchWordMail procedure to run when a user clicks the HTML Word Mail icon on the Items toolbar:

    Set cmdNewButton = cbrNewToolbar.Controls.Add _
        (Type:=msoControlButton) 'Custom button for Word Mail
        With cmdNewButton
            .FaceId = 42
            .BeginGroup = True
            .Visible = True
            .Style = msoButtonIcon
            .Caption = "HTML Word Mail"
            .OnAction = "LaunchWordMail"
        End With

Note   If you have more than one procedure with the name LaunchWordMail in different code modules, none of the procedures will run when the button is clicked. Outlook must be able to resolve the procedure name specified in the OnAction property for the procedure to run correctly. You cannot use traditional basOutlook.LaunchWordMail syntax to call a procedure in a specified module.

An equivalent OnAction property exists for the CommandBarComboBox controls. Combo box controls run the OnAction procedure when a change event fires. Button controls run the OnAction procedure when a Click event fires. If the Change event causes the OnAction procedure to run, you can examine the ListIndex property of the control to determine the combo box item selected by the user.

If you have multiple controls that point to the same procedure in their OnAction property, use the Parameters property of the control to determine whichcontrol has been clicked. You set the Parameters property of the control when you add the control to its command bar. The ActionProperty of the CommandBar object returns an object representing the control that has been clicked or changed. This example shows how you can use the Parameter and ActionControl properties to branch code execution depending on the Parameter property:

    Dim ctlCBarControl  As CommandBarControl
    Set ctlCBarControl = _
       Application.ActiveExplorer.CommandBars.ActionControl
    If ctlCBarControl Is Nothing Then Exit Function
    'Examine the Parameter property of the ActionControl to determine
    'which control has been clicked
    Select Case ctlCBarControl.Parameter
        Case "Next"
        'Next code here
            olItems.GetNext
        Case "Previous"
        'Previous code here
            olItems.GetPrevious
    End Select

Showing and Enabling Controls

Use the Visible property of a control to show or hide the control on a command bar. Use the Enabled property to enable or disable the control on the toolbar. When a control is disabled, it is still visible but the user cannot perform an action on it. The following function toggles the state of a command bar control. To test this function, type ?CBCtlToggleVisible("Tools", "&Options…") in the Debug window and press Enter to toggle the Enabled property of the Options command on the Explorer Tools menu.

Function CBCtlToggleVisible(strCBarName As String, _
        strCtlCaption As String) As Boolean 
    Dim ctlCBarControl As CommandBarControl
    On Error Resume Next

    Set ctlCBarControl = Application.ActiveExplorer _
        .CommandBars(strCBarName).Controls(strCtlCaption)
    ctlCBarControl.Visible = Not ctlCBarControl.Visible
    If Err = 0 Then
        CBCtlToggleVisible = True
    Else
        CBCtlToggleVisible = False
    End If
End Function

The Visible property is not the only factor that determines whether a specific menu item is visible on a given menu. If personalized menus are turned on with the AdaptiveMenus property, you can use the IsPriorityDropped property to determine whether a menu item is visible on the command bar. If the control's Visible property is set to True, the control will not be immediately visible on a personalized menu if IsPriorityDropped is True.

Note   To determine when to set IsPriorityDropped to True for a specific menu item, Outlook counts the number of times the menu item was used and records the different application sessions in which the user employs another menu item in the same menu as this menu item, without using the specific menu item itself. When this value reaches a threshold, the count is decreased. When the count reaches zero, IsPriorityDropped is set to True. You cannot set the session value, the threshold value, or the IsPriorityDropped property. You can, however, use the AdaptiveMenus property to disable adaptive menus for specific menus in an application.

Determining the State of a Control

The State property of a control tells you whether a button control is in the down or up position. The State property is read-only for built-in controls. A good example of a built-in control that displays state is the Folder List control on the Advanced toolbar. When the control's state equals msoButtonDown, the button is depressed on the toolbar. If the control's state equals msoButtonUp, the button is not depressed on the toolbar. This code examines the state of the Folder List button on the Advanced toolbar:

Function DisplayFolderListState()
    Dim ctlCBarButton As CommandBarButton
    Set ctlCBarButton = Application.ActiveExplorer _
        .CommandBars("Advanced").Controls("Folder List")
    Select Case ctlCBarButton.State
        Case msoButtonUp
            MsgBox "Folder List Hidden", vbInformation
        Case msoButtonDown
            MsgBox "Folder List visible", vbInformation
    End Select
End Function

Adding Separators Between Controls

If you want to add a separator between buttons on a command bar, set the BeginGroup property for the control to True. Group separators on a toolbar provide important visual clues for the user about the relationship of controls. The following example adds a group separator before the Choose Form control on the Items toolbar:

Set cmdNewButton = cbrNewToolbar.Controls.Add _
   (Type:=msoControlButton, ID:=1910) 'Choose Form...
cmdNewButton.BeginGroup = True     'Group Separator

Finding a Control

To find a control on a built-in or custom command bar, use the FindControl method. The FindControl method takes several arguments that facilitate your search. The following example performs a nonrecursive search of the Standard toolbar for the Find A Contact combo box. If a control with a type of msoControlComboBox is found on the Standard toolbar and that control's caption is Find A Contact, the Text property of the combo box is set to the name of a contact. Setting the combo box Text property causes Outlook to search for the contact name as though a user had actually typed a name into the combo box. If the search completes successfully, Outlook displays the Inspector for the contact item.

Sub ContactFindMethod()
    Dim ctlCBarCombo As CommandBarComboBox
    Dim cbrMenuBar As CommandBar
    On Error Resume Next
    Set cbrMenuBar = Application.ActiveExplorer.CommandBars("Standard")
    Set ctlCBarCombo = _
        cbrMenuBar.FindControl (Type:=msoControlComboBox,
          Recursive:=False)
    If ctlCBarCombo = "Find a Contact" Then 'Caption is default 
      Property
        ctlCBarCombo.Text = "Susan Chainey"
    End If
End Sub

Using Control Events

Command bar controls raise two separate events: Click and Change. You can use these events in place of the OnAction property to run an event procedure when a user action or program code causes an event to fire. The table on the following page displays the control and command bar events.

Event Source Object Occurs
OnUpdate CommandBars When any change occurs to a built-in or custom command bar, or to the state of a control on a command bar.
Click CommandBarButton When a button or menu item is clicked.
Change CommandBarComboBox When a user makes a selection in a drop-down list box or a combo box. The Change event also occurs when text is changed in an edit box.

More Info   Be aware that you cannot use control events when writing VBScript code in an Outlook custom form. In this case, you must use the OnAction property to specify the Sub procedure in your code that runs when a toolbar button is clicked.

To write an event procedure for a command bar control

  1. Declare an object variable by using the WithEvents keyword in the declarations section of ThisOutlookSession or in the class module for your COM Add-in project.
  2. Select the object in the Object box of the class module's code window.
  3. Select the event name in the Procedure box of the class module's code window.
  4. Write event procedure code to respond to the Click or Change event.

The CommandBarButton Object

The CommandBarButton object represents a button control on a command bar. We have already discussed in detail many of the properties and methods of the CommandBarButton object. For additional information, search for CommandBarButton in Outlook Visual Basic Reference Help. The Outlook 2000 and Outlook 2002 Explorer and Inspector command bars offer major improvements over command bars in previous versions of Outlook. You can create custom command bars for an Inspector in a previous version of Outlook if you use the Office 97 CommandBars object. However, custom command bars in Outlook 97 and Outlook 98 do not persist between Outlook sessions and cannot be created for the Explorer window. You can use the Execute method to cause built-in commands to run, but the functionality and customization potential of toolbars is limited in previous versions of Outlook.

Note   For additional information regarding command bars in previous versions of Outlook, see the following articles in the Microsoft Knowledge Base:

The CommandBarComboBox Object

The CommandBarComboBox object represents a Combo box or an Edit box control on a command bar. When you add the combo box to a command bar, you specify the type of combo box in the Add method. The following table lists some of the unique properties, methods, and events of a CommandBarComboBox object.

Type Name Description
Property DropDownLines Returns or sets the number of items displayed in the drop-down list box. If the number of items in the list is greater than DropDownLines, a scroll bar appears in the drop-down list box.
  DropDownWidth Returns or sets the width in pixels of the combo box drop-down.
  ListCount Returns the number of items in the list.
  ListIndex Returns or sets the index of the selected item in the list.
  Text Returns or sets the text in the edit portion of the control.
Method AddItem Adds an item to the list.
  Clear Clears the items in the list.
  RemoveItem Removes an item from the list.
Event Change Occurs when a user changes the selection in a combo box or the text in an edit box.

The CommandBarPopup Object

The CommandBarPopup object represents a pop-up control on a command bar. Pop-up controls are unique in that every control contains a CommandBar property object. You can use the CommandBar object to access the child controls of a CommandBarPopup object. The following example uses the CommandBar property object to add additional buttons to the pop-up control:

Set ctlCBarPopup = cbTesting.Controls.Add(Type:=msoControlPopup)
Set cbTestPopup = ctlCBarPopup.CommandBar
Set ctlCBarControl = cbTestPopup.Controls.Add(Type:=msoControlButton)
ctlCBarControl.Caption = "Red"
Set ctlCBarControl = cbTestPopup.Controls.Add(Type:=msoControlButton)
ctlCBarControl.Caption = "Green"
Set ctlCBarControl = cbTestPopup.Controls.Add(Type:=msoControlButton)
ctlCBarControl.Caption = "Blue"
With ctlCBarPopup
    .Caption = "Test Popup"
End With

The AddressLists Collection Object

Outlook users often have several address books from which they can select recipients for a message. The AddressLists collection object contains all the address books available to a user. Using the AddressLists object, you can reference one or more AddressList objects, each of which represents a single address book.

Important   Open the AddressLists collection object, AddressEntries collection object, and the AddressEntry object items in the VBScript Samples folder to work directly with this code in Outlook.

The AddressLists collection object is always referenced from the NameSpace object.

AddressLists Collection Methods

This section covers the Item method of the AddressLists collection object.

Iterating through a collection of address lists

You can use the Item method of the AddressLists collection object to iterate through a collection of address books. The following example uses the Count property of the AddressLists collection object to determine the number of AddressList objects referenced by the collection. It then uses the Item method of the AddressLists collection object to return and display the name of each address book.

Sub ShowAddressLists_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressLists = MyNameSpace.AddressLists
    MsgBox "There are " & MyAddressLists.Count & " address lists.", _
      VbInformation
    For i = 1 to MyAddressLists.Count
        Set MyAddressList = MyAddressLists.Item(i)
        MsgBox MyAddressList.Name & " is " & i & " of " _
          & MyAddressLists.Count, vbInformation
    Next
End Sub

The AddressList Object

The AddressList object represents a single Outlook address book that contains a set of AddressEntry objects. The AddressEntry objects, in turn, can be accessed through the AddressEntries property of the AddressList object.

Outlook Security   If your code attempts to access an AddressEntries collection object or an AddressEntry object, the Warning dialog box shown in Figure 11-4 (on page 429) will be displayed. See Chapter 13 for methods to eliminate the Warning dialog box.

The AddressEntries Collection Object

The AddressEntries collection object is provided by the AddressEntries property of the AddressList object. It provides access to each of the AddressEntry objects contained within a given address book.

AddressEntries Collection Methods

This section covers the Add and Item methods of the AddressEntries collection object.

Adding an address entry

You can use the Add method of the AddressEntries collection object to create a new item in an address book. The following example uses the Add method to create a new entry in the Personal Address Book. The Update method of the AddressEntry object is required to commit the new item to the address book.

Sub AddAddressEntry_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyEntries = MyAddressList.AddressEntries
    Set myEntry = MyEntries.Add _
        ("SMTP","James Allard","jamesallard@microsoft.com")
    myEntry.Update
End Sub

Iterating through a collection of address entries

You can use the Item method of the AddressEntries collection object to iterate through the items in an address book. The following example uses the Count property of the AddressEntries collection object to return the number of items in the user's Personal Address Book. It also uses the Item method of the AddressEntries collection object to return each item in the address book and then display its name.

Sub ShowAddressEntries_Click
    On Error Resume Next
    Set MyPage = Item.GetInspector.ModifiedFormPages _
        ("AddressEntries Collection")
    Set ListBox1 = MyPage.Controls("ListBox1")
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyAddressEntries = MyAddressList.AddressEntries
    For i = 1 to MyAddressEntries.Count
        Set MyEntry = MyAddressEntries.Item(i)
        ListBox1.AddItem MyEntry.Name
    Next
End Sub

The AddressEntry Object

The AddressEntry object represents an individual item in an address book. The AddressEntry object contains information about one or more individuals or processes to which the messaging system can send messages. If the AddressEntry object represents a distribution list—that is, if its DisplayType property is set to olDistList or olPrivateDistList—it can contain additional AddressEntry objects that can be accessed through its Members property.

AddressEntry Object Methods

This section covers the Details,Update,Delete, and GetFreeBusy methods of the AddressEntry object.

Displaying details of an address entry

The Details method of the AddressEntry object displays a modal dialog box that lets a user see (and, if permissions allow, change) the information stored in the Address Book item represented by the object.

The following example steps through the items in a user's Personal Address Book, using the Details method to display the information contained in each item. If the user clicks OK in the dialog box, the next entry is displayed. If the user clicks the Cancel button in the dialog box, an error is produced. For this reason, an On Error statement is included to prevent the routine from exiting immediately, and the Err global variable is tested to determine if it is not zero (which would indicate that the user clicked Cancel or that an error had occurred).

Sub DisplayEntryDetails_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyAddressEntries = MyAddressList.AddressEntries
    On Error Resume Next
    For i = 1 to MyAddressEntries.Count
        Set MyEntry = MyAddressEntries.Item(i)
        MyEntry.Details
        If err <> 0 Then Exit Sub
    Next
End Sub

Changing an address entry

If you have the appropriate permissions, you can change the Address, Name, and Type properties of an AddressEntry object. To commit the change to the address book, you use the object's Update method. The following example converts the Name property of an AddressEntry object to all uppercase characters:

Sub ChangeAddressEntry_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyEntries = MyAddressList.AddressEntries
    Set MyEntry = MyEntries.Item(1)
    MyEntry.Name = Ucase(MyEntry.Name)
    MyEntry.Update
End Sub

Deleting an address entry

The Delete method of the AddressEntry object removes an item from the address book. The following example steps through the items in the Personal Address Book and deletes the first item where the type is set to Sample:

Sub DeleteAddressEntry_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyEntries = MyAddressList.AddressEntries
    MsgBox "Adding a sample entry...", vbInformation
    Set MyEntry = MyEntries.Add ("SAMPLE","Sample Entry","sampleentry")
    MyEntry.Update
    MyEntry.Details
    Set MyEntry = MyEntries.GetFirst
    Do While TypeName(MyEntry) <> "Nothing"
        If MyEntry.Type = "SAMPLE" Then
            MsgBox "Deleting "& MyEntry, vbCritical
            MyEntry.Delete
        Exit Sub
        End If
        Set MyEntry = MyEntries.GetNext
    Loop

    MsgBox "No sample entries found.", vbInformation
End Sub

Getting free/busy information for a user

You can determine whether someone is available at a given time using the GetFreeBusy method of the AddressEntry object. This method returns a string representing 30 days of free/busy information starting at midnight on a specified date. Each character in the string is a digit that indicates whether the person is available during a specified time period. You can specify that the string should indicate only whether the person is available, or you can specify that you want the string to indicate whether a busy time is marked as tentative or out of office.

For example, the following code example returns a string 1440 characters long (48 half-hour periods over 30 days) containing 0 for each half-hour period the person is free, 1 for each period the person has a busy time marked tentative, 3 for each period the person has a busy time marked out of office, and 2 for other busy periods:

MyStatus = MyAddressEntry.GetFreeBusy("7/1/98",30,True)

The following code example returns a string 720 characters long (24 one-hour periods over 30 days) containing 0 for each hour the person is free and 1 for each hour the person is busy, regardless of how the busy periods are designated:

MyStatus = MyAddressEntry.GetFreeBusy("7/1/98",60,False)

The following example displays the next time a person is busy. In addition to Outlook objects and methods, it uses the following VBScript functions:

  • InputBox To prompt the user for the name of the person whose first busy time is to be checked.
  • Date To retrieve the current date.
  • FormatDateTime To convert the retrieved date to the format required by GetFreeBusy.
  • InStr To determine the location (offset) of the first 1 character in the string returned by GetFreeBusy.
Sub GetFreeBusyInformation_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Global Address List")
    If MyAddressList Is Nothing Then
        MsgBox "Global Address List Unavailable!", vbExclamation
        Exit Sub
    End If
    Set MyEntries = MyAddressList.AddressEntries
    MyName = InputBox("Find first busy time for:")
    If MyName <> "" then
        Set MyEntry = MyEntries(MyName)
        If Err Then
            MsgBox "Could not find " & MyName, vbCritical
        Exit Sub
        End If
        StartDate = FormatDateTime(Date,2)
        MyBusyTime = MyEntry.GetFreeBusy(StartDate,60)
        MsgBox MyEntry.Name & " is busy " & InStr(MyBusyTime,"1")-1 _
            & " hours after 12:00 am " & StartDate
    End If
End Sub

AddressEntry Properties

You can use such properties as Name, Address, Members, Type, and Manager to retrieve useful information contained in the item.

More Info   For a complete list and description of the methods and properties for the AddressEntry object, see Microsoft Outlook Visual Basic Reference Help.

The following example uses the Members, Name, and Address properties of the AddressEntry object to display the name and address of each member of a private distribution list named Department:

Sub DisplayListMembers_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyAddressList = MyNameSpace.AddressLists("Personal Address 
      Book")
    If MyAddressList Is Nothing Then
        MsgBox "Personal Address Book Unavailable!", vbExclamation
        Exit Sub
    End If
    MyName = InputBox("Display entries in this Personal Distribution 
      List:")
    If MyName <> "" Then
        Set MyDistList = MyAddressList.AddressEntries(MyName)
        If Err Then
            MsgBox "Could not find " & MyName, vbCritical
            Exit Sub
        End If
        Set MyAddressEntries = MyDistList.Members
        For i = 1 to MyAddressEntries.Count
            Set MyEntry = MyAddressEntries.Item(i)
            MsgBox MyEntry.Name & " " & MyEntry.Address
        Next
    End If
End Sub

Using CDO to Obtain Recipients

Collaboration Data Objects (CDO) is an object model that assists in building messaging and collaboration applications. CDO serves as a complementary object model to manipulate MAPI folders and items from Visual Basic or VBScript code. You can use CDO to access messaging objects which are not available in the Outlook Object Model. For example, the Address procedure shown next lets you present an AddressBook dialog box to the user. When the user makes recipient selections from the AddressBook dialog box, the resolved recipient names are stored in the user-defined field CDORecipients on the AddressEntry object example form in the VBScript Samples folder.

Outlook Security   Access to Recipients, AddressEntries, and AddressEntry objects is also blocked in the CDO Object Model by the Outlook E-Mail Security Update component of Outlook 2002. Unlike blocked Outlook objects, properties, and methods, you cannot create trusted CDO code that eliminates the Warning dialog boxes using the Administrative form in public folders. However, there are third-party alternatives for accessing CDO properties, methods, and objects in a trusted context.

Sub GetRecipients_Click()
    Address "CDORecipients", "Recipients"
End Sub

Sub Address(strUDFieldName, strShortName)
    Dim I
    Dim strRecip
    On Error Resume Next
    strDialogCaption = "Select " & strUDFieldName
    Set objCDO = Application.CreateObject("MAPI.Session")
    'Piggyback on existing Outlook session
    objCDO.Logon "", "", False, False, 0
    If Err Then
        MsgBox "Could not establish CDO session!", vbCritical
    End If
    Set Recips = objCDO.AddressBook(Nothing, _
        strDialogCaption, False, True, 1, strShortName, "", "", 0)
    'These recipients have been resolved by forceResolution argument 
      above
    If Not Err Then
        For i = 1 To Recips.Count
            strRecip = strRecip & Recips(i).Name & "; "
        Next
        If strRecip <> "" Then
            strRecip = Left(strRecip, Len(strRecip)-2)
            Userproperties(strUDFieldName) = strRecip
        End If
    End If
    objCDO.Logoff
End Sub

Installing Collaboration Data Objects

Unfortunately, CDO is not installed by default with Outlook 2002. This practice reverses Microsoft's default CDO installation for Outlook 98. CDO provides functionality for many of the examples in this book and must be installed for the examples to operate correctly. The setup program for the companion CD automatically installs CDO, or CDO can be installed manually.

To install Collaboration Data Objects

  1. Insert the Office XP CD-ROM into your CD-ROM drive.
  2. Click Start, click Settings, and then click Control Panel.
  3. Double-click Add/Remove Programs.
  4. On the Install/Uninstall page, click Microsoft Office XP and then click Add/Remove.
  5. In the Microsoft Office XP Maintenance Mode dialog box, click Add Or Remove Features.
  6. Double-click the Microsoft Outlook For Windows item to expand the item in the Microsoft Office XP: Update Features dialog box.
  7. Click the Collaboration Data Objects item under Microsoft Outlook For Windows to expand the item.
  8. Select Run From My Computer.
  9. Click Update Now to complete the installation of Collaboration Data Objects.

The Folders Collection Object

The Outlook Object Model provides two folder objects: a Folders collection object and a MAPIFolder object. The Folders collection object represents multiple folders. The MAPIFolder object, covered later in this chapter, represents a single folder.

The Folders collection object can contain single or multiple folders. The Folders collection object is always referenced from the NameSpace object.

More Info   For a complete list and description of the properties, methods, and events for the Folders collection object, see Microsoft Outlook Visual Basic Reference Help.

Folders Collection Methods

This section covers the Add and Item methods of the Folders collection object.

Adding a folder to the folder list

You can use the Add method of the Folders collection object to add a folder to the Folder List. The following example uses the Add method of the Folders collection object to add a folder called My New Folder to the Building Microsoft Outlook 2002 Applications personal folder (.pst) file:

Sub CommandButton1_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set MyNewFolder = MyFolder.Folders.Add("My New Folder")
End Sub

Iterating through a collection of folders

You can use the Item method of the Folders collection object to iterate through a collection of folders. The following example uses the Count property of the Folders collection object to return the number of folder items in the Folders collection. It also uses the Item method of the Folders collection object to return each folder in the collection and then display its name. You can also use the For Each . . . Next syntax to iterate over the objects in a collection object.

Sub IterateThroughAFolderCollection_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolders = myNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set MyCollection = myFolders.Folders
    For i = 1 to MyCollection.Count
        set MyFolder = myCollection.Item(i)
        MsgBox MyFolder.Name, vbInformation
    Next
    'For Each…Next provides alternative syntax
    'For Each MyFolder in MyCollection
        'MsgBox MyFolder.Name, vbInformation
    'Next
End Sub

Note   When iterating through a collection of folders or items, the folders or items are not always ordered in the collection based on the date they are received in the folder. If your code depends on a particular order in the collection, use the Sort method of the collection object to control the order of the collection.

The MAPIFolder Object

The MAPIFolder object represents a single Outlook folder. A MAPIFolder object can contain other MAPIFolder objects, as well as Outlook items. This section explains how to move through the Folder List by using the MAPIFolder object and its Folders property.

More Info   For a complete list and description of the properties, methods, and events for the MAPIFolder object, see Microsoft Outlook Visual Basic Reference Help.

Important   Open the MAPIFolder object item in the VBScript Samples folder to work directly with this code in Outlook.

MAPIFolder Object Methods

This section covers the CopyTo and Display methods of the MAPIFolder object.

Copying a folder

You can use the CopyTo method of the MAPIFolder object to create a copy of a folder in another folder. The following example copies the Notes folder to the Inbox:

Sub CommandButton1_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyInboxFolder = MyNameSpace.GetDefaultFolder(6)
    Set MyCurrentFolder = MyNameSpace.GetDefaultFolder(12)
    Set MyNewFolder = MyCurrentFolder.CopyTo(MyInboxFolder)
End Sub

Displaying a folder

You can use the Display method of the MAPIFolder object to display the folder represented by the MAPIFolder object, as shown here:

Sub DisplayAFolder_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.Folders("Public Folders")
    If MyFolder Is Nothing Then
        MsgBox "Public Folders folder not found", vbCritical
            Exit Sub
    End If
    MyFolder.Display
End Sub

MAPIFolder Object Properties

This section covers the DefaultMessageClass, FolderPath, Folders, InAppFolderSyncObject, Items, Parent, Child, EntryID, StoreID, UnReadItemCount, and WebViewURL properties. The Folders property is useful for accessing a folder in the folder list. The Items property is useful for retrieving a collection of items in the folder.

Referencing a folder in the folder list

You can use the Folders property with the MAPIFolder object to return another MAPIFolder object. The OpenMAPIFolder function shown on page 473 is a more efficient way to return a folder in the folder list, compared with the folder-by-folder method illustrated here. In the following procedure, the Folders property is used to move through the various branches of a personal folders list:

Sub ReferenceAFolder_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set BeyondFolder = MyFolder.Folders("4. Beyond the Basics")
    Set VBScriptFolder = BeyondFolder.Folders("VBScript")
    MsgBox VBScriptFolder.Name, vbInformation
End Sub

Iterating through a collection of items in a folder

You can use the Items property of the MAPIFolder object to return a collection of items in the folder. The following example uses the Items property of the MAPIFolder object to return the collection of items in the Inbox folder. It then shows the Subject value of the first five items in the Items collection.

Sub IterateThroughACollectionofItems_Click()
  On Error Resume Next
  Set MyNameSpace = Application.GetNameSpace("MAPI")
  Set MyInboxFolder = MyNameSpace.GetDefaultFolder(6)
  Set MyItems = MyInboxFolder.Items
  For i = 1 to 5
      Set MyItem = MyItems(i)
      Msgbox MyItem.Subject, vbInformation
  Next
End Sub

The EntryID and StoreID properties

The EntryID and StoreID properties of the MAPIFolder object can be used to identify a folder in Outlook. The EntryID property corresponds to the MAPI property PR_ENTRYID. When an object is created, MAPI systems assign a permanent, unique ID string which does not change from one MAPI session to another. The EntryID and StoreID properties, which are analogous to primary keys in a database table, let you identify both Folder and Item objects in the MAPI subsystem. Once you have these values, you can use the GetFolderFromID method to return a MAPIFolder object.

The following example displays the value of the MAPI EntryID and StoreID for the current folder in a message box, displays another message box showing the folder's UnReadItemCount, DefaultMessageClass, and WebViewURL, and then uses the GetFolderFromID method to re-instantiate the Folder object and display the folder:

Sub ShowFolderInfo_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.PickFolder
    If MyFolder Is Nothing Then
        MsgBox "User pressed cancel.", vbInformation
        Exit Sub
    End If
    MsgBox "The Entry ID for the selected folder is:" & vbCr _
        & MyFolder.EntryID & vbCr & vbCr _
        & "The Store ID for the selected folder is:" & vbCr _
        & MyFolder.StoreID, vbInformation
    MsgBox MyFolder.UnReadItemCount & " of " & MyFolder.Items.Count _
        & " items are unread." & vbCr _
        & "The default message class is: _
        & MyFolder.DefaultMessageClass & vbCr _
        & "The folder URL is: " & MyFolder.WebViewURL, vbInformation
    Set MyFolder = MyNameSpace.GetFolderFromID _
        (MyFolder.EntryID, MyFolder.StoreID)
    MyFolder.Display
End Sub

Making a folder available for offline use

You can programmatically make a folder available for offline use by using the InAppFolderSyncObject property. Somewhat mysteriously named, the InAppFolderSyncObject property determines whether the folder will be added to the Application Folders Send/Receive group. For additional information on Send/Receive groups and offline use, see Chapter 8, "Folders." The following code example adds the Top Accounts folder to the Application Folders group and starts a synchronization programmatically:

Sub SyncTopAccounts()
    Dim objFolder As Outlook.MAPIFolder
    Dim objAppSync As SyncObject
    Dim objOutlook As Outlook.Application
    Set objOutlook = CreateObject("Outlook.Application")
    Set objFolder = objOutlook.GetNamespace("MAPI") _
      .GetDefaultFolder(olFolderInbox)
    Set objFolder = objFolder.Folders("Top Accounts")
    objFolder.InAppFolderSyncObject = True
    Set objAppSync = ThisOutlookSession.GetNamespace("MAPI") _
      .SyncObjects.AppFolders
    objAppSync.Start
End Sub

Returning a folder from a folder path

The OpenMAPIFolder procedure allows you to return a MAPIFolder object if you supply a folder path as an argument. A folder path is expressed as follows:

Set objFolder = OpenMAPIFolder _
  ("\Public Folders\All Public Folders\Sales\Q401")

Function OpenMAPIFolder(ByVal strPath) 'As MAPIFolder
    Dim objFldr 'As MAPIFolder
    Dim strDir 'As String
    Dim strName 'As String
    Dim i 'As Integer
    On Error Resume Next
    If Left(strPath, Len("\")) = "\" Then
        strPath = Mid(strPath, Len("\") + 1)
    Else
        Set objFldr = Application.ActiveExplorer.CurrentFolder
    End If
    While strPath <> ""
        i = InStr(strPath, "\")
        If i Then
            strDir = Left(strPath, i - 1)
            strPath = Mid(strPath, i + Len("\"))
        Else
            strDir = strPath
            strPath = ""
        End If
        If objFldr Is Nothing then
            Set objFldr = 
              Application.GetNameSpace("MAPI").Folders(strDir)
            On Error Goto 0
        Else
            Set objFldr = objFldr.Folders(strDir)
        End If
    Wend
    Set OpenMAPIFolder = objFldr
End Function

Note   The type declarations have been commented out in the OpenMAPIFolder and GetFolderPath functions. If you want to use these functions in VBA or Visual Basic code, remove the comment marks.

Returning a folder path from a folder

If you are using a version of Outlook prior to Outlook 2002, the GetFolderPath function allows you to return a string representing a folder path if you supply a MAPIFolder object as an argument. If you are using Outlook 2002, you simply use the FolderPath property of the MAPIFolder object to return a string that contains the folder path.

Function GetFolderPath(ByVal objFolder) 'As String
    On Error Resume Next
    Dim strFolderPath 'As String
    Dim objChild 'As MAPIFolder
    Dim objParent 'As MAPIFolder
    strFolderPath = "\" & objFolder.Name
    Set objChild = objFolder
    Do Until Err <> 0
        Set objParent = objChild.Parent
        If Err <> 0 Then
            Exit Do
        End If
        strFolderPath = "\" & objParent.Name & strFolderPath
        Set objChild = objParent
    Loop
    GetFolderPath = strFolderPath
End Function

Displaying a folder Web view

One of the exciting features of Outlook is the ability to display Web views in the Explorer View pane. The following example sets the WebViewURL for your Drafts folder to the MSDN Online Exchange Developer Center and then displays the Web view of the folder. The WebViewOn property is then set to False to restore the default view on the folder.

Sub DisplayFolderWebView_Click
    On Error Resume Next
    Set MyNS = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNS.GetDefaultFolder(16) 'Drafts folder
    MyFolder.WebViewURL = "http://msdn.microsoft.com/exchange"
    MyFolder.WebViewOn = True
    MyFolder.Display
    MsgBox "Click OK to Reset Web View", vbInformation
    MyFolder.WebViewOn = False 'Reset
    'Re-instantiate the MAPIFolder object
    Set MyFolder = MyNS.GetDefaultFolder(16) 'Drafts folder
    MyFolder.Display
End Sub

New Outlook 2002 Folder Properties

In addition to the InAppFolderSyncObject property discussed previously, Outlook 2002 adds some MAPIFolder properties that are worth noting. The ShowAsOutlookAddressBook property determines whether a Contacts folder will be displayed as an Outlook Address Book. If the folder is not a Contacts folder, setting the property has no effect. The AddToPFFavorites property adds a public folder to the Favorites folder so that it's available for offline use. The following example adds a folder named Classified Ads to the Favorites folder:

Sub AddClassifiedToPFFavorites()
    Dim oFolder As Outlook.MAPIFolder
    Dim oApp As Outlook.Application
    Set oOutlook = CreateObject("Outlook.Application")
    Set oFolder = _
       oApp.GetNamespace("MAPI") _
         .GetDefaultFolder(olPublicFoldersAllPublicFolders)
    Set oFolder = objFolder.Folders("Classified Ads")
    oFolder.AddToPFFavorites
End Sub

The Views Collection Object

The Views collection object, which is new in Outlook 2002, is a property object of the MAPIFolder object. You can use the Views collection object to enumerate the Views in a folder or to obtain a child View object and change the View programmatically. You can also use the Add method to add a View to a folder. The following example creates a View named Larger View in the CurrentFolder object of the ActiveExplorer object. For a more thorough explanation of modifying Views programmatically with the XML DOM (eXtensible Markup Language Document Object Model), see the Outlook View Wizard example in Chapter 14.

Sub CreateLargerView()
    Dim objView As Outlook.View
    Dim colViews As Outlook.Views
    Dim objXMLDOM As New MSXML2.DOMDocument30
    Dim objNode As MSXML2.IXMLDOMNode
    Dim objOutlook As Outlook.Application
    Dim objActExpl As Outlook.Explorer
    Set objOutlook = CreateObject("Outlook.Application")
    'Get the Active Explorer
    Set objActExpl = objOutlook.ActiveExplorer
    'Obtain the Views collection for the current folder
    Set colViews = objActExpl.CurrentFolder.Views
    'Create a new view named Larger View
    Set objView = colViews.Add _
      ("Larger View", _
      olTableView, _
      olViewSaveOptionThisFolderEveryone)
    'Load the XML for the new view into XML DOM object
    objXMLDOM.loadXML (objView.XML)
    'This is the element that we will modify
    strElement = "view/rowstyle"
    'Get the node object for view/rowstyle
    Set objNode = objXMLDOM.selectSingleNode(strElement)
    'Change the font size to 14pt
    objNode.nodeTypedValue = "font-size:14pt"
    'Assign the XML for View to objXML.XML
    objView.XML = objXMLDOM.XML
    'Save the View
    objView.Save
    'Apply the View in the folder
    objView.Apply
End Sub

The Items Collection Object

Items are the discrete packages of information represented by a Mail Message, a Post item, a Contact item, a Distribution List item, a Document item, a Journal item, a Meeting Request, a Note, or a Task item. You use the Items property to return the Items collection of a MAPIFolder object. The single item object is represented by the following objects:

  • AppointmentItem object An Appointment item.
  • ContactItem object A Contact item.
  • DistListItem object A Distribution List item.
  • DocumentItem object A Document item.
  • JournalItem object A Journal item.
  • MailItem object A Mail Message item.
  • MeetingItem object A Meeting item.
  • NoteItem object A Note item.
  • PostItem object A Post item.
  • ReportItem object A Mail delivery report item.
  • TaskItem object A Task item.
  • TaskRequestAcceptItem An item sent to accept a Task request.
  • TaskRequestDeclineItem An item sent to decline a Task request.
  • TaskRequestItem An item sent to assign a Task.
  • TaskRequestUpdateItem An item sent to update a Task request.

This section covers some of the methods and properties of the Items collection object. Sections that follow this section—beginning with "The PostItem Object" on page 481—cover the methods and properties of specific Item objects.

More Info   For a complete list and description of the properties, methods, and events for the Items collection object, see Microsoft Outlook Visual Basic Reference Help.

Important   Open the Items collection object item in the VBScript Samples folder to work directly with this code in Outlook.

Items Collection Object Methods

This section covers the Add,Find, and Restrict methods of the Items collection object.

Creating a custom item

With Outlook, there are two basic methods of creating items. Standard items such as Message items (IPM.Note), Post items (IPM.Post), and Contact items (IPM.Contact) are created using the CreateItem method of the Application object, as discussed earlier in this chapter.

To create custom items, however, such as an IPM.Post.Product Idea item, you use the Add method of the Items collection object. For example, to create a Product Idea item (IPM.Post.Product Idea) for the Product Ideas folder, you must first return the Items collection object, and then use the Add method of the Items collection object to add the new item to the collection. The custom item has the methods and properties of the item upon which is it based. For example, an item with the message class IPM.Post.Product Idea contains the methods and properties of the PostItem object, in addition to the custom UserProperties defined for IPM.Post.Product Idea. If you create an item with the message class IPM.Note.Orders, you use the MailItem object.

Important   Before you can create a custom item, the form associated with the item must exist in the forms library of the folder in which the item is created. For example, to create a Product Idea item, the Product Idea form must exist in the Product Ideas Folder forms library or in the Personal or Organizational Forms Libraries.

The following example references the Product Ideas folder and then creates a Product Idea item and displays it. Note that the Product Idea form exists in the Product Ideas folder forms library.

Sub CreateACustomItem_Click()
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
    ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set MyItems = ProductIdeasFolder.Items
    Set MyItem = MyItems.Add("IPM.Post.Product Idea")
    MyItem.Subject = "VBScript Test"
    MyItem.Body = "This is a test"
    MyItem.Display
End Sub

Important   Note that in the preceding procedure, the Body property of the single Item object corresponds with the Message field on the form. For more details about the properties of standard items, see "MailItem and PostItem Objects Properties" later in this chapter.

Finding an item in a folder

You can use the Find method of the Items collection object to find an item in a folder based on the conditions you specify.

Important   If you are using user-defined fields as part of a restriction argument of a Find or Restrict method, the user-defined fields must exist in the folder; otherwise, the code will raise an error and the Find or Restrict method will fail. You can add a field to a folder by displaying the Field Chooser and clicking New.

The following example uses the Find method of the Items collection object to return the first item in the Product Ideas folder with the value Boating in the Product Category field:

Sub FindAnIteminAFolder_Click ()
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set MyItem = ProductIdeasFolder.Items.Find _
        ("[Product Category] = 'Boating'")
    MyItem.Display
End Sub

Creating a filtered collection of items from a folder

You can use the Restrict method of the Items collection object to create filters that return only those items in a folder matching the conditions you specify.

More Info   For more information about constructing filter expressions, see Find Method and Restrict Method in Microsoft Outlook Visual Basic Reference Help.

The following example returns the collection of items from the Product Ideas folder and then creates a filtered collection of items with only the value Boating in the Product Category field:

Sub CreateAFilteredCollection_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set MyItems = ProductIdeasFolder.Items
    Set MyFilter = MyItems.Restrict("[Product Category] = 'Boating'")
    MsgBox "There are " & MyFilter.Count & " Boating items.", 
      vbInformation
End Sub

Note   The Restrict method does not offer optimal performance for a large collection of items in a folder. If you need to iterate over hundreds or thousands of items in a folder, use the SetColumns method to cache specified properties and increase performance. Only certain Item properties can be cached with the Restrict and SetColumns methods. User-defined properties cannot be cached with SetColumns. See Restrict Method and SetColumns Method in Microsoft Outlook Visual Basic Reference Help for additional information.

Sorting the items in a filtered collection

If you want to sort the items in the Items collection, use the Sort method. Currently, the Sort method only supports sorting on built-in properties for the Item. The example below creates a restricted collection of Contacts in your mailbox that have an Email1Address value. After the restriction has been created, the Sort method is used on the filtered Items collection object. Finally the first item is the Sorted Items collection is displayed.

Sub SortAFilteredCollection_Click
    On Error Resume Next
    olFolderContacts = 10
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = MyNameSpace.GetDefaultFolder(olFolderContacts)
    Set MyItems = myFolder.Items
    'Create the Filter first and then sort
    Set MyFilter = MyItems.Restrict("[Email1Address] <> ''")
    'Sort by LastName in descending order
    MyFilter.Sort "[LastName]", True
    'Display the first item in the filter
    MyFilter.Item(1).Display
End Sub

Important   The Sort method will return an error if you attempt to sort for built-in multi-valued properties such as Companies and Categories. You also cannot sort by a user-defined field unless the user-defined field is defined in the folder. The Sort method is effective, from a performance standpoint, only for small collections of items.

Deleting the items in a collection

If you want to delete items from an Items collection object, you can't use the For i = 1 to MyItems.Count . . . MyItems.Item(i).Delete . . . Next routine or the For Each myItem in MyItems . . . myItem.Delete . . . Next routine you would normally use to iterate over the items in the collection. The following example is a generic function that will delete all the items in the Items collection passed as an argument to the function:

Function DeleteAllItems(myItems) 'MyItems is an Items collection object
    On Error Resume Next
    Do Until MyItems.Count = 0
        MyItems.Remove 1
    Loop
End Function

Items Collection Object Properties

This section explains how to use the Count property.

Returning the count of items in the items collection

You can use the Count property of the Items collection object to return the number of items in the Items collection. This provides an easy way to loop through collections to process a large number of items, as shown in the previous example. The following example returns the number of items in the Inbox and shows the number in a message box:

Sub CommandButton1_Click()
    On Error Resume Next
    Set MyFolder = _
       Item.Application.GetNameSpace("MAPI").GetDefaultFolder(6)
    Set MyItems = MyFolder.Items
    MsgBox "You have " & MyItems.Count _
        & " items in your Inbox.", vbInformation
End Sub

The PostItem Object

The PostItem object represents a message posted in a public folder. Unlike a MailItem object, a PostItem object is not sent to a recipient. This section covers some of the methods of the PostItem object. Properties of the PostItem object are similar to the properties of the MailItem object, so they are discussed together in "MailItem and PostItem Objects Properties" later in this chapter.

PostItem Object Methods

The PostItem object provides a variety of methods that you can use to control the actions of an item. This section covers the Copy, Move, Delete, Display, and Post methods.

Copying and moving an item

You can use the Copy method of the PostItem object to create a copy of an item. You can then use the Move method to move the copied item to a new location.

The example on the following page returns the first item in the Product Ideas folder with the value Boating in the Product Category field. It then uses the Copy method to create a copy of the item returned from the Product Ideas folder. If the user selects Yes in the message box, the Move method copies the item from the Product Ideas folder to the Drafts folder. If you want to move rather than copy the item, use the Delete method and place a MyItem.Delete statement after the MyItem.Copy statement.

Sub CopyAndMove_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set MyItem = ProductIdeasFolder.Items.Find _
        ("[Product Category] = 'Boating'")
    If MyItem Is Nothing Then
        MsgBox "Could not find an item.", vbInformation
    Else
        strQuestion = "Copy " & MyItem.Subject & " to Drafts?"
        If MsgBox(strQuestion, vbQuestion+vbYesNo) = vbYes Then
            Set MyCopiedItem = MyItem.Copy
            'MyItem.Delete if a move instead of copy
            Set DestinationFolder = MyNameSpace.GetDefaultFolder(16)
            myCopiedItem.Move DestinationFolder
            MsgBox MyItem.Subject & " copied to Drafts.", vbInformation
        End If
    End If
End Sub

Creating and displaying a custom post item

You can use the Display method of the PostItem object to display an item on the desktop. As discussed earlier, you use the Add method of the Items collection object to create a new custom Post item. The following example returns the Product Ideas folder and then creates a new custom PostItem object by using the Add method of the Items collection object. It then displays the item in the Product Idea form. If you click the Post button on the form, the item is posted in the Product Ideas folder.

Sub CreateAndDisplay_Click()
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set MyItem = ProductIdeasFolder.Items.Add("IPM.Post.Product Idea")
    myItem.Subject = "Handlebar polish"
    myItem.UserProperties("Product Category") = "Cycling"
    myItem.Body = "For cyclists who want their bikes to gleam in the 
      wind."
    MyItem.Display
End Sub

Posting an item

You can use the Post method of the PostItem object to post an item in a folder. The following example sets the folder to the Product Ideas folder. It then creates a new item with the message class IPM.Post.Product Idea, which is added to the Product Ideas Items collection. In this procedure, the object returned to MyItem by the Add method has a base message class of IPM.Post so you can use the Post method. The Subject and Body properties of the MyItem object are set, and then the item is posted to the Product Ideas folder.

Sub PostanItem_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set BldFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set QuickFolder = BldFolder.Folders("2. Quick Guide")
    Set ProductIdeasFolder = QuickFolder.Folders("Product Ideas")
    Set myItem = ProductIdeasFolder.Items.Add("IPM.Post.Product Idea")
    myItem.Subject = "VBScript is versatile"
    myItem.Body = "Let's develop new products using this technology."
    myItem.Post
    MsgBox myItem.Subject & _
        " has been posted in the Product Ideas folder.", vbInformation
End Sub

The MailItem Object

The MailItem object represents a message in a mail folder. This section also covers some of the methods and properties of the PostItem object. Properties of the PostItem object are similar to the properties of the MailItem object, so they are discussed together.

Important   Open the MailItem object and PostItem object items in the VBScript Samples folder to work directly with this code in Outlook.

MailItem Object Methods

This section covers the Send, Reply, and Close methods of the MailItem object.

If your code attempts to send a message programmatically, the Warning dialog box shown in Figure 11-9 will be displayed. See Chapter 13 for methods to eliminate the Warning dialog box.

Aa155615.odc_c11612730-09(en-us,office.10).gif

Figure 11-9. This Warning dialog box appears when you attempt to send a message programatically.

Sending a message

You can use the Send method of the MailItem object to send a message to a recipient. The following example creates a Mail Message item, sets the Subject and message Body fields, and then sets the To field to your name. You can retrieve the ScriptText property of the FormDescription object for the item to set the Body property of the message. It then uses the Send method to send the item to the specified recipient.

Note   The Body property of the item only lets you set plain text as the message text. If you want to format the Body programmatically, use the HTMLBody property discussed on page 487.

Sub SendAMessage_Click
    Set MyItem = Application.CreateItem(olMailItem)
    MyItem.Subject = "VBScript Code for MailItem object"
    Set MyForm = Item.FormDescription
    MyItem.Body = MyForm.ScriptText
    MyItem.To = Application.GetNameSpace("MAPI").CurrentUser
    MyItem.Send
End Sub

Replying to a message

You can use the Reply method of a MailItem object to return a Reply item. The following example creates a Reply item based on the current item, and then returns the Reply item represented by the MyReply object. The Reply item is then displayed. To run this example, you must first put a CommandButton1 control on the Read page of a Mail Message form. Exit Design mode and send the item to your Inbox, and then open the item in the Inbox and click CommandButton1. The Reply item is displayed.

Sub CommandButton1_Click
    Set MyFolder = Application.GetNameSpace("MAPI").GetDefaultFolder(6)
    Set MyItem = MyFolder.Items.Item(1)
    Set MyReply = MyItem.Reply
    MyReply.Display
End Sub

Closing an item

You can use the Close method of the MailItem object to close an item. When you close the item, you also close the item's associated form. The following example closes the current item when the CloseAnItem button is clicked. Note that if the blnIsDirty script-level variable is True, then the user is prompted to save changes. If blnIsDirty is False, then the item is closed and changes are not saved. You could modify this procedure to automatically save changes to a dirty form. This example also illustrates how you can write event procedures in the code for your custom form to control how and when the form is saved.

Dim blnIsDirty

Sub Item_PropertyChange(ByVal Name)
    blnIsDirty = True
End Sub

Sub Item_CustomPropertyChange(ByVal Name)
    blnIsDirty = True
End Sub

Function Item_Write()
    blnIsDirty = False
End Function

Sub CloseAnItem_Click
    Const olSave = 0
    Const olDiscard = 1
    Const olPromptForSave = 2
    If blnIsDirty = True Then
        Item.Close olPromptForSave
    Else
        Item.Close olDiscard
    End If
End Sub

You can use one of the arguments in the table on the following page with the Close method or use CONST declarations as shown in the preceding example.

Save Option Value
Save all changes without prompting 0
Discard all changes without prompting 1
Prompt to save or discard all changes 2

Note   Unlike previous versions of Outlook, Outlook 2000 and 2002 allow you to write VBA or Visual Basic code to respond to all the events that are raised in a Message item. For additional information, see Chapter 9 and Chapter 14.

MailItem and PostItem Objects Properties

This section covers the GetInspector, Body, HTMLBody, To, and SenderName properties of the MailItem and PostItem objects.

Using GetInspector to reference the form

You can use the GetInspector property of the MailItem object or the PostItem object to reference the form associated with an item. You can then reference the page on the form, and then the controls on the page. The following example uses the GetInspector property of the MailItem object to return the form associated with the item. It references the Message page on the form and then sets the Visible property of the TextBox1 control to False.

Before you run this example, do the following:

  1. If you don't have a TextBox1 control on the form, click Design This Form from Forms on the Tools menu to switch to Design mode.
  2. Drag a TextBox control from the Control Toolbox to the form.
  3. Click Run This Form on the Form menu to switch to Run mode, and then click CommandButton1 to hide the TextBox1 control.
Sub CommandButton1_Click
    Set MyPage = GetInspector.ModifiedFormPages("Message")
    MyPage.TextBox1.Visible = False
End Sub

Setting the message text of an item

You can use the Body property of a MailItem object or a PostItem object to specify the text that appears in the Message control of a Mail Message. The following example creates a Reply item, enters text in the Message control of the Reply item, and then sends the form:

Sub CommandButton1_Click()
    Dim MyFolder, MyItem, MyReply
    Set MyFolder = Application.GetNamespace("MAPI").GetDefaultFolder(6)
    Set MyItem = MyFolder.Items(1)
    Set MyReply = MyItem.Reply
    MyReply.Body = "Let's go to the Napa Valley next weekend."
    MyReply.Display
End Sub

Note   The Body property does not support Rich Text Format (RTF) or HyperText Markup Language (HTML).

You can also use the HTMLBody property of a MailItem or PostItem object to specify formatted text in the Message control. When you set this property, Outlook automatically sets the EditorType property of the associated Inspector object to olEditorHTML(2).

New to Outlook 2002   The BodyFormat property provides an easier way to specify the format of a message than the HTMLBody and Body properties. Be aware that if you change the BodyFormat property from RTF to HTML or vice versa, the formatting of the message will be lost. The BodyFormat property is available only for MailItem and PostItem objects.

The following example displays the current editor type, sets the HTMLBody property of the item, and then displays the new editor type. Open the HTMLBody Object form in the VBScript Samples folder to see a more sophisticated example of using the HTMLBody property. You can create HTML dynamically in the VBScript code behind a form and then present that HTML in the body of an Item.

Sub CommandButton1_Click
    On Error Resume Next
        strHTML= "<body bgcolor='cyan'>" _
           & "<H1>This is HTML text.</H1>" _
           & "<body>"
    Item.HTMLBody = strHTML
End Sub

Note   For additional information on the Body property, see Knowledge Base article Q291153-OL2002: Working With the Message or Body of an Outlook Item.

Setting the To field of an item

You can use the To property of the MailItem object to set the value of a To field. The following example creates a new item and then sets the To field and Subject field values of the item:

Sub CommandButton1_Click
    Set MyItem = Application.CreateItem(0)
    MyItem.To = "someone@somecompany.com"
    MyItem.Subject = "How to set the To field"
    MyItem.Display
End Sub

Outlook Security   As long as you display the MailItem object and allow the user to click the Send button rather than sending programmatically, the Warning dialog box shown earlier in Figure 11-9 will not appear.

Getting the sender name of an item

You can use the SenderName property of the MailItem object to return the name of the person who sent the message. The following example gets the first item in the Inbox and sets the Recip variable to the value of the SenderName property. It then creates a new Message item and sets its To field to the value of the Recip variable. When the item is displayed, the value of the SenderName property shows in the To box of the form.

Sub GetTheSenderName_Click
    Set MyFolder = Application.GetNameSpace("MAPI").GetDefaultFolder(6)
    Set MyItem = MyFolder.Items(1)
    Recip = MyItem.SenderName
    Set MyNewItem = Application.CreateItem(0)
    MyNewItem.To = Recip
    MyNewItem.Display
End Sub

Note   In the preceding example, the name in the To field is not resolved. To resolve a name, the name must be added to the Recipients collection object. For more information, see "The Recipients Collection Object" later in this chapter.

Getting the sender address of an item

The Outlook Object Model does not provide a means to obtain the e-mail address of the item's sender. To obtain the e-mail address of the sender, you can use CDO to create a Sender object for the MAPI Message object. The Sender object exposes several useful properties, one of which is the Address property. The following VBA code displays a message box containing the e-mail address for the sender of the first item in the Inbox:

Sub GetSender()
    Dim objCDO As MAPI.Session
    Dim objMsg As MAPI.Message
    Dim objSender As MAPI.AddressEntry
    Dim oMsg As Outlook.MailItem
    Dim strMsg As String
    On Error Resume Next
    Set oMsg = Application.ActiveExplorer.Selection.Item(1)
    Set objCDO = CreateObject("MAPI.Session")
    objCDO.Logon "", "", False, False
    Set objMsg = objCDO.GetMessage(oMsg.EntryID)
    Set objSender = objMsg.Sender
    strMsg = "Subject: " & objMsg.Subject & vbCrLf _
        & "Sender Name: " & objSender.Name & vbCrLf _
        & "Sender e-mail: " & objSender.Address & vbCrLf _
        & "Sender type: " & objSender.Type
    MsgBox strMsg, vbInformation
End Sub

Outlook Security   When you set the objSender variable, you access a CDO AddressEntry object. This will cause the Warning dialog box shown in Figure 11-4 (on page 429) to appear.

Adding attachments to an item

You can add attachments to an item programmatically by using the Add method of the Attachments collection object. VBScript's FileSystemObject lets you write and read from a file programmatically. Therefore, you can write to a file and then attach the file to a message in code. Open the FileSystemObject item in the VBScript Samples folder to see this code in action.

Sub WriteandAttachFile_Click()
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
    Const olByValue = 1, olByReference = 4, olEmbeddeditem = 5, 
      olOLE = 6
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")
    strPath = GetTempDir & "\FSObject.txt"
    Set objFile = fso.OpenTextFile(strPath, ForAppending, True)
    strLine = Now & " - " & "This file demonstrates use " _
        & "of the FileSystemObject to write to a text file."
    objFile.Write(strLine)
    objFile.Close
    Set objMsg = Application.CreateItem(0)
    Set colAttachments = objMsg.Attachments
    colAttachments.Add strPath, olByValue, 1, "FileSystemObject
Attachment"
    objMsg.Subject = "FileSystemObject Object"
    objMsg.Display
End Sub

Function GetTempDir
    Const TemporaryFolder = 2, SystemFolder = 1, WindowsFolder = 0
    On Error Resume Next
    Dim fso, tfolder
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set tfolder = fso.GetSpecialFolder(TemporaryFolder)
    If Err then
        GetTempDir = "Could not obtain temporary folder path."
        Exit Function
    End If
    GetTempDir = lcase(tFolder.Path)
End Function

The DocumentItem Object

The DocumentItem object represents an assortment of different items that can be stored in Outlook folders. To clarify what a DocumentItem object represents, the terms extrinsic and intrinsic DocumentItems need to be defined. A DocumentItem object can be a file that is dragged to an Outlook folder from Windows Explorer. It can also result from a file posted to an Exchange public folder from a source application such as Microsoft Word, Excel, or PowerPoint. These items are extrinsic DocumentItem objects, meaning that they were created by an application extrinsic to Outlook. An extrinsic DocumentItem has the following characteristics:

  • The DocumentItem was created by its native application or an object model supported by its native application.
  • The item does not support Outlook DocumentItem properties, methods, and events.
  • You cannot create a custom Outlook form from an extrinsic DocumentItem.

Because extrinsic DocumentItem objects do not support Outlook Inspector properties and events, you cannot automate these items easily within the container of an Outlook folder. For example, you cannot write an Item_Open event procedure for an extrinsic DocumentItem object. Some applications—most notably Microsoft Excel—still support a native Open event that fires when a user opens the document. This event fires whether the Excel document exists in an Outlook folder or in the file system. A DocumentItem object can also be an Outlook 2000 DocumentItem that wraps an Inspector object around an Office document. You cannot create an Outlook 2000 DocumentItem in Outlook 2002. Outlook 2000 DocumentItems are supported in Outlook 2002, but you cannot design a new DocumentItem in Outlook 2002. For additional details, see "Inspectors Collection Events" in Chapter 9. A user creates an Outlook Office Document Item in Outlook 2000 only by selecting the Office Document command from the New submenu of the File menu in Outlook Explorer. There are only four types of Outlook 2000 DocumentItems that you can create from within Outlook: Word Documents, Excel Charts, Excel Worksheets, and PowerPoint Presentations. These Outlook 2000 DocumentItems are known as intrinsic DocumentItems. An intrinsic DocumentItem object has the following characteristics. Be aware that this list applies only to DocumentItems created in Outlook 2000.

  • They support Outlook DocumentItem properties, methods, and events.
  • They can be either a Post-type or Send-type DocumentItem. When you design an Outlook DocumentItem, you will see a dialog box asking you if you want to send the document to someone or post the document in this folder. Whatever your choice, Outlook does not distinguish between a Post or Send DocumentItem in the message class of the custom form.
  • You can create a custom Outlook form from an intrinsic DocumentItem. This custom form will have a base message class equivalent to the message class of the extrinsic DocumentItem. If you create a custom DocumentItem named Sales Analysis from a Word DocumentItem, the message class of the custom form will be IPM.Document.Word.Document.8.Sales Analysis.
  • You can write VBScript code behind the DocumentItem custom form.
  • These Outlook DocumentItems have the same base message class as extrinsic DocumentItems. In all cases, DocumentItems are actually attachments to a message container with a message class of IPM.Document. The following table lists some important types of DocumentItems that can be placed in an Outlook folder.
Document Item Message Class Outlook DocumentItem with Inspector Custom Form Built on Item Document Open Event
Web Page IPM.Document. htmlfile No No Use DHTML to create window onload event.
Word Document IPM.Document. Word.Document.8 Yes Yes No. See workaround below.
Excel Worksheet IPM.Document. Excel.Sheet.8 Yes Yes Yes.
PowerPoint Presentation IPM.Document. PowerPoint.Show.8 Yes Yes No.
Adobe Acrobat Document IPM.Document. AcroExch.Document No No No.
Visio Drawing IPM.Document.Visio. Drawing.5 No No No.
Other Document Types IPM.Document.<Document Class> No No Depends on the object model and VBA support in the source application.

Creating a Word DocumentItem

You can create a Word DocumentItem programmatically in a folder as long as you have Word installed. Creating a DocumentItem programmatically is a two-step process. First create a DocumentItem with the correct message class in the target folder. To complete the process, use the Attachments collection of the DocumentItem to add an appropriate attachment to the DocumentItem. The following VBA example uses Word Automation to create a Word document in the temporary folder. The Word document is then attached to a Word DocumentItem created in the user's Inbox. Finally the Word document in the temporary folder is deleted. The same basic sequence would be followed if you wanted to create an Excel workbook instead of a Word document.

Sub AddDocumenttoInbox()
    Dim objWordDoc As DocumentItem
    Dim wdApp As Word.Application
    Dim wdDoc As Word.Document
    Dim objFolder As MAPIFolder
    On Error Resume Next
    Set objFolder = _
        Application.GetNameSpace("MAPI").GetDefaultFolder
          (olFolderInbox)
    Set objWordDoc = 
      objFolder.Items.Add("IPM.Document.Word.Document.8")
    Set wdApp = CreateObject("Word.Application")
    Set wdDoc = wdApp.Documents.Add
    With wdApp.Selection
        .TypeText "Microsoft Outlook 2002"
        .TypeParagraph
        .TypeText "A great tool for communication and collaboration!"
    End With
    'GetTempDir returns trailing \
    strPath = GetTempDir() & "O2KTest2.doc"
    wdDoc.SaveAs strPath
    wdDoc.Close
    'Save the DocumentItem with wdDoc attachment
    With objWordDoc
        .Subject = "Microsoft Outlook 2002"
        .Attachments.Add (strPath)
        .Save
    End With
    'Delete wdDoc in temp folder
    Kill strPath
End Sub

Firing the Word Document Open Event

One problem with intrinsic DocumentItems based on Microsoft Word is that the Document_Open event does not fire when the DocumentItem is opened from an Outlook folder. If you build an application based on a Word DocumentItem, you'll want to be able to use the Document_Open event so that code can assign values to bookmarks, insert and format text, and fill tables from an external database, if necessary. In short, the Document_Open event is the gateway to automating your custom DocumentItem form from Word VBA code embedded in the DocumentItem, rather than from VBScript code in the Item_Open event.

You'll find a workaround for this problem in the Document_Open Workaround item located in the VBScript Samples folder. The workaround uses the VBScript GetObject function to return a reference to the Word Application object. Because the document embedded in the DocumentItem object represents the ActiveDocument in the Word Application object, you can instantiate a Word Document object and use the AutoRunMacro method on that object to fire the Document_Open event. In order for the following example to work correctly, you might have to lower the Macro Security settings in Word. In this example, the Document_Open event displays a message box indicating the word count for the document:

Sub Item_Open()
    On Error Resume Next
    'Get CurrentUser
    strUser = Application.GetNameSpace("MAPI").CurrentUser
    Set objWord = GetObject(, "Word.Application")
    'Use Word TypeText to insert some sample text
    strText = "The CurrentUser is: " & strUser
    objWord.Selection.TypeText strText
    objWord.Selection.TypeParagraph
    'Run the Document_Open procedure with RunAutoMacro method
    Set objDoc = objWord.ActiveDocument
    Const wdAutoOpen = 2
    objDoc.RunAutoMacro wdAutoOpen
    Item.Subject = "DocumentItem Word Document_Open Workaround"
    'Use Built-in properties to set subject and author
    Const wdPropertySubject = 2
    Const wdPropertyAuthor = 3
    objDoc.BuiltinDocumentProperties(wdPropertySubject) = _
        "Document_Open Workaround"
    objDoc.BuiltinDocumentProperties(wdPropertyAuthor) = strUser
    'Optional: Use CustomDocumentProperties to set additional fields
End Sub

Private Sub Document_Open()
    Dim strMsg As String
    strMsg = "This document contains " _
        & ThisDocument.BuiltInDocumentProperties(wdPropertyWords) _
        & " words."
    MsgBox strMsg, vbInformation, "Document Open Event"
End Sub

Using DocumentProperties with DocumentItem Objects

One of the great, but little known, features of Outlook is the ability to place documents in folders and expose both the BuiltInDocumentProperties and CustomDocumentProperties objects of the document in folder views. The DocumentProperties object is exposed for all applications in the Office suite, except Outlook. Each DocumentProperty object represents a built-in or custom property of a container document. DocumentProperties are, in turn, divided into BuiltInDocumentProperties and CustomDocumentProperties. Each Office application exposes a subset of the BuiltInDocumentProperties collection object. If you are building an application around a folder containing DocumentItems, you can add BuiltInDocumentProperties to folder views.

To add built-in document properties to a Folder View

  1. Navigate to the folder where you want to establish the view.
  2. On the Advanced toolbar, click the Field Chooser icon.
  3. Select All Document Fields in the drop-down list box at the top of the Field Chooser window.
  4. Drag appropriate fields to the folder View.

More Info   For additional information about the DocumentProperties collection object, see DocumentProperties in the Microsoft Office Visual Basic Reference Help.

To use Custom Document Properties in a folder view, you must add the CustomDocumentProperties fields to the folder as user-defined fields in the folder. The following example assumes that you have installed the Expense Statement template for Excel 2002. (If you have not installed the Expense Statement template, it will demand to be installed the first time you attempt to create a workbook based on that template.)

To create an Expense Statement Document

  1. Launch Excel 2002.
  2. Select New from the File menu.
  3. Double-click Expense Statement on the Spreadsheet Solutions page of the New dialog box.
  4. Complete the Expense Statement template by clicking the Select Employee button and adding expense report information.
  5. Select Send To from the File menu, and then select Exchange Folder from the Send To submenu. If you are not using an Exchange Server, you can save the file to a file system folder and then drag the Expense Statement workbook from the file system to an Outlook folder.

To add custom document properties to a Folder View

  1. In the folder where you placed the Expense Statement report, click the Field Chooser icon on the Advanced toolbar.
  2. Select User-Defined Fields In Folder in the drop-down list box at the top of the Field Chooser window.
  3. Click the New button to create a new user-defined field in the folder.
  4. Enter Employee Name as the name of the user-defined field, and click OK.
  5. Drag the Employee Name field into the folder view.
  6. In the Field Chooser, click New again.
  7. Enter Total Reimbursement/Payment as the name of the user-defined field.
  8. Select Number in the Type drop-down list box.
  9. Click OK.
  10. Drag the Total Reimbursement/Payment field into the folder view.
  11. You should now see the values of the Custom Document Property fields displayed in the view in the folder.

The AppointmentItem Object

An AppointmentItem object represents an appointment in the Calendar folder. An AppointmentItem object can represent a one-time appointment, a meeting, or recurring appointments and meetings. A meeting usually involves more than one person and is created when an AppointmentItem is sent to other users, who then receive it in the form of a MeetingItem object in their respective Inbox folders.

An appointment or meeting can be recurring—that is, set to occur more than once on a regular or repetitive basis. When this occurs, a RecurrencePattern object is created for the AppointmentItem object. An instance of a recurring appointment can be changed or deleted. This creates an exception to the recurrence pattern, and this exception is represented by an Exception object. All Exception objects associated with a given AppointmentItem object are contained in an Exceptions collection object associated with the AppointmentItem.

Important   Open the AppointmentItem object in the VBScript Samples folder to work directly with this code in Outlook. The object contains advanced CDO code (not shown in this chapter) that lets you programmatically set the color label property. Color appointments are new to Outlook 2002.

Working with Recurring Appointments

This section covers recurring appointments, including how to create a recurring appointment and how to deal with exceptions to the recurrence pattern.

Creating a recurring appointment

A recurring appointment is represented by an AppointmentItem object with the IsRecurring property set to True. However, you cannot set this property directly. Instead, you create a recurring appointment by calling the GetRecurrencePattern method of the AppointmentItem object and then saving the item. The following example illustrates how to create an appointment named Test Appointment and then call the GetRecurrencePattern method to make it a recurring appointment:

Sub CreateRecurringAppointment_Click
    Set MyItem = Application.CreateItem(1)
    MyItem.Subject = "Test Appointment"
    Set MyPattern = MyItem.GetRecurrencePattern
    MyItem.Save
End Sub

The GetRecurrencePattern method returns a RecurrencePattern object. You can change the recurrence pattern of the appointment by setting properties of the appointment's RecurrencePattern object.

Setting the recurrence pattern of an appointment

When a new recurring appointment is created, it inherits a default recurrence pattern based on the time the appointment was created. To change the recurrence pattern of an appointment, set the appropriate properties of the appointment's RecurrencePattern object.

More Info   For more information about the properties of the RecurrencePattern object affecting the recurrence pattern, see Microsoft Outlook Visual Basic Reference Help.

The following example shows how to create a one-hour recurring appointment that occurs at noon on the second Tuesday of each month for two months, starting July 2001:

Sub SetRecurrencePattern_Click
    Set MyItem = Application.CreateItem(1)
    MyItem.Subject = "Monthly Appointment"
    Set MyPattern = MyItem.GetRecurrencePattern
    MyPattern.RecurrenceType = 3 'Monthly, on a specific weekday
    MyPattern.Interval = 1 'Every month (2 would be every other month)
    MyPattern.DayOfWeekMask = 4 'Which day of week (Tuesday)
    MyPattern.Instance = 2 'Which instance (second Tuesday)
    MyPattern.StartTime = "12:00 pm" 'Time each appointment begins
    MyPattern.EndTime = "1:00 pm" 'Time each appointment ends
    MyPattern.PatternStartDate = #7/1/2001# 'Earliest date appt can 
      Occur
    MyPattern.PatternEndDate = #9/1/2001# 'Latest date appt can occur
    MyItem.Save
End Sub

Working with a Single Appointment in a Series

To determine whether an instance of a recurring appointment occurs at a particular time, use the GetOccurrence method of the RecurrencePattern object. This method returns an AppointmentItem object representing the instance of the recurring appointment.

Important   The GetOccurrence method will produce an error if an instance of the recurring appointment does not start at the date and time you provide. If it is possible that your script can supply a date and time that does not match an instance of a recurring appointment (because of user input, for example), the script should be able to handle the error appropriately. Otherwise, the script procedure will fail and Outlook will display an error message.

The following example illustrates how to use the GetOccurrence method to determine whether a recurring appointment (created by the code in the previous section) starts on a date and time provided by the user. The On Error Resume Next statement ensures that the procedure will continue if the user enters anything that does not match the start date and time of an instance of the recurring appointment. After calling the GetOccurrence method, the script tests the MyAppointment variable to determine whether it is set to Nothing, indicating that the method failed and did not return an AppointmentItem object.

Sub CheckOccurrence_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyCalendarFolder = MyNameSpace.GetDefaultFolder(9)
    Set MyItem = MyCalendarFolder.Items("Monthly Appointment")
    Set MyPattern = MyItem.GetRecurrencePattern
    On Error Resume Next
    MyDate = InputBox ("Enter a date and time (m/d/yy hh:mm): ")
    Do While MyDate <> ""
        Set MyAppointment = Nothing
        Set MyAppointment = MyPattern.GetOccurrence(MyDate)
        If TypeName(MyAppointment) <> "Nothing" Then
            MsgBox "This instance of " & MyAppointment.Subject _
                & " occurs on " & MyAppointment.Start
        Else
            MsgBox MyItem.Subject & " does not occur on " & MyDate
        End If
        MyDate = InputBox _
            ("Enter another date and time (m/d/yy hh:mm):")
    Loop
End Sub

Once you retrieve the AppointmentItem object representing an instance of a recurring appointment, you can delete or change the appointment instance. When this happens, Outlook creates an Exception object. The properties of this object describe the changes that were made to the instance. All of the Exception objects for a recurring appointment are contained in an Exceptions collection object associated with the appointment's RecurrencePattern object.

The AppointmentItem property of the Exception object returns the AppointmentItem object that constitutes the exception to the original recurrence pattern of the recurring appointment. You can use the methods and properties of the AppointmentItem object to work with the appointment exception. The following example changes the subject of an instance of the recurring appointment created by the script in the previous section. It then uses the AppointmentItem property of the resulting Exception object to change the start time of the appointment exception.

Sub CreateException_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyCalendarFolder = MyNameSpace.GetDefaultFolder(9)
    Set MyItem = MyCalendarFolder.Items("Monthly Appointment")
    Set MyPattern = MyItem.GetRecurrencePattern
    Set MyInstance = MyPattern.GetOccurrence(#8/14/2001 12:00 pm#)
    MyInstance.Subject = "Monthly Pattern (exception)"
    MsgBox MyInstance.Subject & " starts on " & MyInstance.Start
    MyInstance.Save
    Set MyNewPattern = MyItem.GetRecurrencePattern
    Set MyException = MyNewPattern.Exceptions.Item(1)
    Set MyNewInstance = MyException.AppointmentItem
    MyNewInstance.Start = (#8/14/2001 1:00 pm#)
    MsgBox MyNewInstance.Subject & " now starts on " & 
      MyNewInstance.Start
    MyNewInstance.Save
End Sub

The following two sections describe how to use the Exception object to work with changed or deleted instances of a recurring appointment.

Determining the Original Date of an Exception

The OriginalDate property of the Exception object returns the start date and time of the changed appointment before it was changed. The following example uses the OriginalDate property to retrieve the original start date of the appointment exception created in the previous section. In addition, it uses the Start property of the AppointmentItem associated with the Exception object to provide the new start date of the appointment.

Sub ShowOriginalDate_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyCalendarFolder = MyNameSpace.GetDefaultFolder(9)
    Set MyItem = MyCalendarFolder.Items("Monthly Appointment")
    Set MyPattern = MyItem.GetRecurrencePattern
    Set MyException = MyPattern.Exceptions.Item(1)
    MsgBox "The changed appointment originally occurred on " _
        & MyException.OriginalDate & Chr(13) & "It now occurs on "_
        & MyException.AppointmentItem.Start, vbInformation
End Sub

Determining Whether an Appointment Instance Was Deleted

When an appointment in a recurring series is deleted, an Exception object representing the deleted appointment is created, and the Deleted property of the Exception object is set to True. The following example uses the Delete method of the AppointmentItem object to delete the appointment instance changed in the previous section. It then tests the value of the Deleted property of the Exception object representing the deleted appointment to determine whether the appointment was actually deleted.

Sub CheckIfDeleted_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyCalendarFolder = MyNameSpace.GetDefaultFolder(9)
    Set MyItem = MyCalendarFolder.Items("Monthly Appointment")
    Set MyPattern = MyItem.GetRecurrencePattern
    Set MyAppointment = MyPattern.GetOccurrence(#8/14/2001 1:00 pm#)
    MyAppointment.Delete
    Set MyException = MyPattern.Exceptions.Item(1)
    If MyException.Deleted Then MsgBox "The appointment was deleted."
End Sub

The MeetingItem Object

Important   Open the MeetingItem object in the VBScript Samples folder to work directly with this code in Outlook.

A MeetingItem object represents a request for a meeting received in a user's Inbox mail folder. You cannot create a MeetingItem object directly. Instead, Outlook creates a MeetingItem object in each recipient's Inbox folder when a user sends an AppointmentItem object with its MeetingStatus property set to olMeeting(1). The following example shows how to create an appointment and then send the appointment as a meeting request to a required attendee and an optional attendee:

Sub SendMeetingRequest_Click
    Set myItem = Application.CreateItem(1) 'Create an appointment
    myItem.MeetingStatus = 1 'Appointment is a meeting
    myItem.Subject = "Marketing Strategy Meeting"
    myItem.Location = "Conference Room B"
    myItem.Start = #9/24/2001 1:30:00 PM#
    myItem.Duration = 90
    myAttendee = InputBox ("Enter name of Required Attendee")
    If myAttendee <> "" then
        Set myRequiredAttendee = myItem.Recipients.Add(MyAttendee)
        myRequiredAttendee.Type = 1 'Required
    End If
    myAttendee = InputBox ("Enter name of Optional Attendee")
    If myAttendee <> "" then
        Set myOptionalAttendee = myItem.Recipients.Add(MyAttendee)
        myOptionalAttendee.Type = 2 'Optional
    End If
    myItem.Send
End Sub 

The MeetingItem object replaces the MeetingRequestItem object provided by Outlook 97.

Working with Meeting Requests

Most often, you will not work directly with a MeetingItem object. For example, you do not use the MeetingItem object to accept or decline the meeting. Instead, you use the appointment associated with the meeting request.

The GetAssociatedAppointment method of the MeetingItem object returns an AppointmentItem object that you can use to accept or refuse the meeting request or to directly add the meeting (as an appointment) to the Calendar folder.

You can also directly access an AppointmentItem that has its MeetingStatus property set to olMeeting(1) to determine which recipients have accepted or declined the meeting request. The following sections illustrate how to work with a meeting request through the appointment associated with the meeting.

Retrieving the associated appointment of a meeting

The MeetingItem object is a message containing a request to add an appointment to the recipient's calendar; it is not the appointment itself. To access the appointment associated with the meeting request, you use the GetAssociatedAppointment method of the MeetingItem object. This method requires a Boolean argument that specifies whether the appointment is added to the user's Calendar.

The following example calls the GetAssociatedAppointment method of each MeetingItem in the user's Inbox and then uses the returned AppointmentItem object's Display method to open the appointment. Note that the argument of GetAssociatedAppointment is set to False so that the appointment is not added to the user's Calendar.

Sub DisplayMeetingRequests_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myItems = myFolder.Items
    Set myMeetingRequest = _
        myItems.Find("[MessageClass] = 'IPM.Schedule.Meeting.Request'")
    Do While TypeName (myMeetingRequest)<> "Nothing"
        myMeetingRequest.GetAssociatedAppointment(False).Display
        Set myMeetingRequest = myItems.FindNext
    Loop
End Sub

Responding to a meeting request

To respond to a meeting request, you use the GetAssociatedAppointment method of the MeetingItem object to obtain the AppointmentItem object associated with the meeting request. You then use the Respond method of the AppointmentItem object to notify the meeting organizer whether the meeting has been accepted, declined, or tentatively added to the receiving user's Calendar.

The Respond method allows you to send the notification without user intervention, or it can allow the user to edit the response before sending it. The Respond method accepts three parameters: the first specifies the actual response (accept, decline, or tentative), while the second two are Boolean values that determine whether the user will be given the opportunity to edit the response.

Outlook Security   Code that utilizes the Respond method without requiring action by the user is blocked by the Outlook E-Mail Security Update in Outlook 2002. If you run the AutoAcceptMeetingRequest procedure shown next, you will see the Warning dialog boxes we looked at earlier. If you want most of the code in this section to run without prompts, you will have to wrap the code into a COM Add-in and then add the COM Add-in to the list of trusted COM Add-ins.

To send the notification without requiring action by the user, you call the Respond method with the second parameter set to True and then send the AppointmentItem as shown in the following example:

Sub AutoAcceptMeetingRequest_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myMtgReq = _
        myFolder.Items.Find("[MessageClass] = _
        'IPM.Schedule.Meeting.Request'")
    If TypeName(myMtgReq) <> "Nothing" Then
        Set myAppt = myMtgReq.GetAssociatedAppointment(True)
        myAppt.Respond 3, True
        myAppt.Send
        MsgBox "The " & myAppt.Subject & " meeting on " & myAppt.Start 
          _
            & " has been accepted.", vbInformation
    Else
        MsgBox "You have no meeting requests in your Inbox.", 
          VbInformation
    End If
End Sub

If you want to allow the user to choose how to respond (that is, whether to send a response and whether to edit the body of the response before sending), call the Respond method with the second parameter set to False and the third parameter set to True, as shown below:

Sub PromptUserToAccept_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myMtgReq = _
        myFolder.Items.Find("[MessageClass] _
           ='IPM.Schedule.Meeting.Request'")
    If TypeName(myMtgReq) <> "Nothing" Then
        Set myAppt = myMtgReq.GetAssociatedAppointment(True)
        myAppt.Respond 3, False, True
    Else
        MsgBox "You have no meeting requests in your Inbox."
    End If
End Sub

You can use the Respond method to display a dialog box that gives the user three choices:

  • Edit The Response Before Sending
  • Send The Response Now
  • Don't Send A Response

Outlook immediately sends the AppointmentItem to the meeting organizer if the user chooses Send The Response Now. If the user chooses Edit The Response Before Sending, Outlook opens the item to allow the user to change recipients, the subject, or the body text before sending the response. Instead of giving the user the choice of how to respond, you can call the Respond method with the second and third parameters both set to False. The result is the same as when the user chooses Edit the response before sending.

Determining the status of a recipient of a meeting request

An AppointmentItem object created from a MeetingItem object has an associated Recipients collection object. You can use the MeetingResponseStatus property of the Recipient objects in this collection to determine whether a given recipient has accepted or declined the requested meeting.

The script in the following example retrieves each meeting that the user has requested and then checks the MeetingResponseStatus property for each recipient of the meeting. A description of the status for each recipient is added to a text string that is displayed in a message box once the status of all the recipients has been checked.

Sub CheckRecipientStatus_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(9)
    Set myItems = myFolder.Items
    Set myMeeting = myItems.Find("[MeetingStatus] = 1")
    Do While TypeName(myMeeting) <> "Nothing"
        TextStr = "The following is the status of recipients for " _
            & MyMeeting.Subject & " on " & MyMeeting.Start & ":" & 
              chr(13)
        Set myRecipients = myMeeting.Recipients
        For x = 1 To myRecipients.Count
            TextStr = TextStr & chr(13)& myRecipients(x).Name
            Select Case myRecipients(x).MeetingResponseStatus
                Case 0
                    TextStr2 = " did not respond."
                Case 1
                    TextStr2 = " organized the meeting."
                Case 2
                    TextStr2 = " tentatively accepted."
                Case 3
                    TextStr2 = " accepted."
                Case 4
                    TextStr2 = " declined."
            End Select
            TextStr = TextStr & TextStr2
        Next
        If MsgBox(TextStr,1) = 2 then Exit Sub ' Use OK/Cancel; exit if 
          Cancel
        Set myMeeting = myItems.FindNext
    Loop
End Sub

More Info   For more information about the MeetingResponseStatus property and the values it returns, see Microsoft Outlook Visual Basic Reference Help.

The TaskItem Object

The TaskItem object represents a single item in the user's Tasks folder. A task is similar to an appointment in that it can be sent to others (much like a meeting request) and can be a recurring task. Unlike an appointment, however, an uncompleted recurring task has only a single instance. When an instance of a recurring task is marked as complete, Outlook creates a second instance of the task for the next time period in the task's recurrence pattern.

This section shows you how to work with a TaskItem object.

Important   Open the TaskItem object and TaskRequestItem object items in the VBScript Samples folder to work directly with this code in Outlook.

TaskItem Object Methods

This section covers the GetRecurrencePattern and Assign methods of the TaskItem object.

Creating a recurring task

You can use the GetRecurrencePattern method of the TaskItem object to create a recurring task, in much the same manner as creating a recurring appointment. (For more information, see "Creating a Recurring Appointment" earlier in this chapter.) The following example shows how to create a task and then call the GetRecurrencePattern method to make the task a recurring task:

Sub CreateRecurringTask_Click
    Set MyItem = Application.CreateItem(3)
    MyItem.Subject = "Test Task"
    Set MyPattern = MyItem.GetRecurrencePattern
    MyItem.Save
End Sub

As with a recurring meeting, you use the RecurrencePattern object associated with the task to specify how often and when the task will recur. Unlike a recurring appointment, however, a recurring task does not have multiple occurrences. Instead, when a recurring task is marked as completed, Outlook creates a copy of the task for the next date in the recurrence pattern. Consequently, the RecurrencePattern object of a task does not support the GetOccurrence method or the Exceptions property.

Delegating a task

In much the same way as you can invite others to a meeting by sending them an AppointmentItem object, you can delegate a task to others by sending them a TaskItem object. Before sending the object, however, you must first use the Assign method to create an assigned task. The following example shows how to create and delegate a task using the Assign and Send methods. Remember that the programmatic Send will cause the Warning dialog box to appear.

Sub AssignTask_Click
    Set myItem = Application.CreateItem(3)
    myItem.Assign
    Set myDelegate = myItem.Recipients.Add("James Allard")
    myItem.Subject = "Develop order confirmation form"
    myItem.DueDate = #6/12/99#
    myItem.Send
End Sub

When a task is assigned and sent to another user, the user receives a TaskRequestItem object. You can use this object to access the task associated with the request and to respond to the task request.

The TaskRequestItem Object

A TaskRequestItem object represents a request to assign a task in the Inbox of the user to whom the task is being assigned. The following example displays a message box containing the subject of each task request in the user's Inbox folder:

Sub ShowTaskRequests_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myItems = myFolder.Items
    Set myTaskRequest = _
        myItems.Find("[MessageClass] = 'IPM.TaskRequest'")
    Do While TypeName (myTaskRequest)<> "Nothing"
        myMessage = myMessage & chr(13) & myTaskRequest.Subject
        Set myTaskRequest = myItems.FindNext
    Loop
    If myMessage = "" then
        MsgBox "You have no pending task requests"
    Else
        MsgBox "Your pending task requests are:" & chr(13) & myMessage
    End If
End Sub

Working with Task Requests

As with a MeetingItem object, usually you will not work directly with a TaskRequestItem object. For example, you do not use the TaskRequestItem object to accept or decline the task. Instead, you use the task associated with the task request.

The GetAssociatedTask method of the TaskRequestItem object returns a TaskItem object that you can use to accept or refuse the task.

Retrieving the associated task of a task request

Using the GetAssociatedTask method, you can access the task associated with a TaskRequestItem. Properties of the TaskItem returned by this method contain additional information about the assigned task, such as its due date.

Important   Before you call the GetAssociatedTask method for a TaskRequestItem object, you must first process the TaskRequestItem object. By default, this is done automatically (unless the user has cleared the Process Requests And Responses On Arrival check box on the Advanced E-Mail Options dialog box available through the Options dialog box). You can also process a TaskRequestItem object by calling its Display method. Note that when a TaskRequestItem object is processed, its associated task is added to the user's Tasks folder.

The following code example displays a message box containing the subject and due date of every task request in the user's Inbox. This example is identical to the one in the previous section, but it uses the GetAssociatedTask method to access the DueDate property of the task associated with the task request. Note that this example assumes that the TaskRequestItem objects have already been processed.

Sub ShowAssociatedTasks_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myItems = myFolder.Items
    Set myTaskRequest = _
    myItems.Find("[MessageClass] = 'IPM.TaskRequest'")
    Do While TypeName (myTaskRequest)<> "Nothing"
        myMessage = myMessage & chr(13) _
            & myTaskRequest.Subject & " due on " _
            & myTaskRequest.GetAssociatedTask(False).DueDate
        Set myTaskRequest = myItems.FindNext
    Loop
    If myMessage = "" then
        MsgBox "You have no pending task requests"
    Else
        MsgBox "Your pending task requests are:" & chr(13) & myMessage
    End If
End Sub

Responding to a task request

To accept, decline, or modify a task request, use the Respond method of the TaskItem object returned by the GetAssociatedTask method of a TaskRequestItem object. The following example retrieves the first TaskRequestItem in the user's Inbox and accepts it. Like the GetAssociatedAppointment method discussed earlier, the Respond method will display the Outlook Object Model Guard dialog boxes.

Sub AcceptTaskRequest_Click
    Set myNameSpace = Application.GetNameSpace("MAPI")
    Set myFolder = myNameSpace.GetDefaultFolder(6)
    Set myItems = myFolder.Items
    Set myTaskRequest = _
        myItems.Find("[MessageClass] = 'IPM.TaskRequest'")
    If TypeName(myTaskRequest) <> "Nothing" then
        Set myTask = MyTaskRequest.GetAssociatedTask(False)
        myTask.Respond 2, True,False
        myTask.Send
        MsgBox "Accepted: " & MyTask.Subject, vbInformation
    Else
        MsgBox "You have no pending task requests", vbInformation
    End If
End Sub

Note that if you set the second parameter of the Respond method to True, you must call the Send method of the TaskItem.

When the Respond method is used to respond to a task request, the initiating user receives a TaskRequestAcceptItem, TaskRequestDeclineItem, or TaskRequestUpdateItem object, depending on the type of response. You work with these objects in much the same way as a TaskRequestItem object in that you use the object's GetAssociatedTask method to retrieve the TaskItem object associated with the request and then call the methods and access the properties of the TaskItem object.

The ContactItem and DistListItem Objects

The ContactItem contains two important collection objects in Outlook 2000 and Outlook 2002. The Links object lets you link child ContactItem objects to parent Item objects. Only ContactItem objects can perform as child objects of a parent MailItem, PostItem, AppointmentItem, DocumentItem, JournalItem, TaskItem, DistListItem, or ContactItem object. Another great feature of the Links object is that Link object members do not have to live in the same folder as the parent item object.

The second collection object that pertains to the ContactItem is the DistListItem. A DistListItem acts as a container for ContactItem objects and, as the name implies, is a means of creating distribution lists in both your mailbox Contacts folder and in public folders. Because the Outlook ContactItem is such a rich form with over 100 properties that support Personal Information Management (PIM), the DistListItem is also a rich container and can be manipulated programmatically by your application.

More Info   For a complete list and description of the properties, methods, and events for the ContactItem and DistListItem objects, see Microsoft Outlook Visual Basic Reference Help.

Important   Open the ContactItem object item in the VBScript Samples folder to work directly with this code in Outlook.

ContactItem Object Methods

This section shows you how to forward a Contact Item as a vCard, the Internet standard for creating and sharing virtual business cards.

Sending the contact as a vCard

This example uses the ForwardasvCard method to forward a vCard attachment for a Contact in a Mail Message. The ForwardasvCard method returns a MailItem with the vCard file attached.

Sub SendAsvCard_Click
    Const olContactItem = 2
    On Error Resume Next
    Set myContact = Application.CreateItem(olContactItem)
    myContact.FirstName = "Nancy"
    myContact.LastName = "Davolio"
    myContact.FullName = "Davolio, Nancy"
    myContact.CompanyName = "AnyCompany Corporation"
    myContact.JobTitle = "Senior Analyst"
    myContact.Department = "ITSD"
    myContact.Email1Address = "nancyd@anycompany.com"
    myContact.Email1AddressType = "SMTP"
    myContact.Display
    Set myMsg = myContact.ForwardasvCard
    myMsg.Display(True) 'Forces modal display
End Sub

Use the Links collection to add Contacts to an existing item. You can add Link items to any Item type. The following example shows you how to use the Add method of the Links collection object to add the last three LastNames in your Contacts folder to a Contact item that was created programmatically. Only items with a base message class of IPM.Contact can be added as a member of the Links collection for an item. You cannot add a DistListItem to the Links collection.

Sub AddItemstoLinks_Click
    Const olContactItem = 2, olFolderContacts = 10
    Set objContact = Application.CreateItem(olContactItem)
    objContact.FirstName = "Jane"
    objContact.LastName = "Smith"
    objContact.FullName = "Smith, Jane"
    objContact.CompanyName = "XYZ Corporation"
    objContact.JobTitle = "Senior Analyst"
    objContact.Department = "ITSD"
    objContact.Email1Address = "jsmith@xyz.com"
    objContact.Email1AddressType = "SMTP"
    Set colLinks = objContact.Links
    'Add the last three names in your contacts folder to links
    Set objNS = Application.GetNameSpace("MAPI")
    Set objFolder = objNS.GetDefaultFolder(olFolderContacts)
    Set colContacts = objFolder.Items
    colContacts.Sort "[LastName]", True 'Descending
    For Each myContact in colContacts
        'Can only add Contacts to Links collection
        If Instr(myContact.MessageClass,"IPM.Contact") Then
            If myContact.Email1Address <> "" Then
                colLinks.Add(myContact)
                intAdded = intAdded + 1
            End If
        End If
        If intAdded = 3 Then Exit For
    Next
    'Contact must be saved for links to work
    objContact.Save
    objContact.Display
End Sub

Adding contacts to a DistListItem

The following example shows you how to programmatically add members to a DistListItem object. The trick is to create a temporary mail item and instantiate a Recipients collection item for that Mail item. Once you have added recipients to the Recipients collection, use the AddMembers method of the DistListItem to add the recipients to the Distribution List. For additional information on the Recipients object, see "The Recipients Collection Object" later in this chapter.

Outlook Security   If your code attempts to access a Recipients collection object, attempts to access a property that relates to a ContactItem e-mail address, or uses the GetMember method of the DistListItem, the Warning dialog box shown earlier in Figure 11-4 (on page 429) will appear. See Chapter 13 for methods to eliminate the Warning dialog box and a detailed discussion of which properties and methods trigger Warning dialog boxes.

Sub AddContactstoDistListItem_Click
    On Error Resume Next
    Const olMailItem = 0, olDistributionListItem = 7, olFolderContacts 
      = 10
    Set objDL = Application.CreateItem(olDistributionListItem)
    'Create a temporary mail item
    Set objMsg = Application.CreateItem(olMailItem)
    Set colRecips = objMsg.Recipients
    'Add the first three names in your contacts folder to links
    Set objNS = Application.GetNameSpace("MAPI")
    Set objFolder = objNS.GetDefaultFolder(olFolderContacts)
    Set colContacts = objFolder.Items
    colContacts.Sort "[LastName]"
    For Each myContact in colContacts
        'Can only add contacts with e-mail address
        If myContact.Email1Address <> "" Then
            colRecips.Add MyContact.Email1Address
            intAdded = intAdded + 1
        End If
        If intAdded = 3 Then Exit For
    Next
    objDL.AddMembers colRecips
    objDL.Subject = "Test DL"
    objDL.Display
End Sub

The JournalItem Object

The JournalItem object provides a convenient way to record activity in relationship to any Outlook item. A journal entry can be as simple as the record of a phone call or as complex as recording the number of times a specific Word document has been edited.

JournalItem Object Methods

Because the JournalItem object records activities in time, the two most important methods of the JournalItem object are the StartTimer and StopTimer methods. The following example creates a Journal Item from a contact, creates a link to the contact for the Journal Item, and then starts the Journal Item timer with the StartTimer method:

Sub LinkJournalItemtoContact_Click
    Const olContactItem = 2, olJournalItem = 4
    On Error Resume Next
    Set myContact = Application.CreateItem(olContactItem)
    myContact.FirstName = "Friedman"
    myContact.LastName = "Fern"
    myContact.FullName = "Friedman, Fern"
    myContact.CompanyName = "XYZ Corporation"
    myContact.JobTitle = "Senior Analyst"
    myContact.Department = "ITSD"
    myContact.Email1Address = "ffriedman@xyz.com"
    myContact.Email1AddressType = "SMTP"
    'Save the contact before you create a link
    myContact.Save
    Set myJournal = Application.CreateItem(olJournalItem)
    myJournal.Companies = myContact.CompanyName
    myJournal.Subject = myContact.Subject
    Set colLinks = myJournal.Links
    colLinks.Add myContact
    myJournal.Display
    myJournal.StartTimer
End Sub

More Info   For a complete list and description of the properties, methods, and events for the JournalItem object, see Microsoft Outlook Visual Basic Reference Help.

Important   Open the JournalItem object in the VBScript Samples folder to work directly with this code in Outlook.

The Item Window (Inspector Objects)

The Inspector object represents the window in which an Outlook item is displayed. The Inspectors object is the parent collection object for Inspector objects. The following sections cover some of the methods and properties for the Inspector and Inspectors objects.

More Info   For a complete list and description of the properties, methods, and events for the Inspector and Inspectors objects, see Microsoft Outlook Visual Basic Reference Help.

Important   Open the Inspector object in the VBScript Samples folder to work directly with this code in Outlook.

Inspector Object Methods

This section covers the SetCurrentFormPage,HideFormPage, and ShowFormPage methods of the Inspector object.

Setting the current form page

You can use the SetCurrentFormPage method of the Inspector object to set the current form page of a form. The following example shows the Details page as the current form page of a Contact form when you click CommandButton1. (To use this example, you must add a command button to a Contact form in Design mode. Add the code in the Script Editor, and then run the form.)

Sub SetTheCurrentFormPage_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set BeyondFolder = MyFolder.Folders("4. Beyond the Basics")
    Set VBScript = BeyondFolder.Folders("VBScript")
    Set VBScriptSamples = VBScript.Folders("VBScript Samples")
    Set MyItem = VBScriptSamples.Items.Add("IPM.Post.Test")
    set MyInspector = MyItem.GetInspector
    MyInspector.SetCurrentFormPage("Test")
    MyItem.Display
End Sub

Hiding and showing a form page

You can use the HideFormPage and ShowFormPage methods of the Inspector object to hide and show a form page. In the following example, the Test page of the Test form is hidden:

Sub HideTheTestPage_Click
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.Folders _
        ("Building Microsoft Outlook 2002 Applications")
    Set BeyondFolder = MyFolder.Folders("4. Beyond the Basics")
    Set VBScript = BeyondFolder.Folders("VBScript")
    Set VBScriptSamples = VBScript.Folders("VBScript Samples")
    Set MyItem = VBScriptSamples.Items.Add("IPM.Post.Test")
    Set MyInspector = MyItem.GetInspector
    MyInspector.HideFormPage("Test")
    MyItem.Display
End Sub

Inspector Object Properties

This section covers the ModifiedFormPages property of the Inspector object. The ModifiedFormPages property returns the entire collection of pages for a form. The Pages collection object is covered in more detail in the next section.

Referencing a form page and its controls

You can use the ModifiedFormPages property of the Inspector object to return the Pages collection representing the pages on a form that have been modified. Note that standard pages on a form, such as a Message page, are also included in the collection if the standard pages can be customized. You must use the Pages collection object to switch to the page, which then allows you to gain access to controls on the page. The following example uses the ModifiedFormPages property of the Inspector object to return the Inspector object page in the Pages collection object. It then uses the Controls property of the Page object to reference the HideandShow toggle button control. When the HideandShow control is down (its value equals True), the HideAndShowLabel control is visible. When the toggle button is up, the HideAndShowLabel control is not visible.

Sub HideAndShow_Click
    Set myInspector = Item.GetInspector
    Set myPage = myInspector.ModifiedFormPages("Inspector Object")
    Set myControl = myPage.Controls("HideAndShow")
    If myControl.value = True Then
        myPage.Controls("HideAndShowLabel").Visible = True
    Else
        myPage.Controls("HideAndShowLabel").Visible = False
    End If
End Sub

The Pages Collection Object

To reference a page or controls on a page, you use the ModifiedFormPages property of the Inspector object to reference the Pages collection object, and then you reference the individual page by name or number. The following procedure uses the ModifiedFormPages property of the Inspector object to return the number of modified form pages in the Pages collection. Note that the pages are not added to the collection until the page is clicked at design time.

Sub ShowModifiedFormPagesCount_Click
    Set PagesCollection = Item.GetInspector.ModifiedFormPages
    MsgBox "The number of modified form pages in the Pages collection 
      is " _
        & PagesCollection.Count & "."
End Sub

Important   Open the Page object item in the VBScript Samples folder to work directly with this code in Outlook.

The Page Object

You can use the ModifiedFormPages property to return the Pages collection from an Inspector object. Use ModifiedFormPages*(index),* where index is the name or index number, to return a single page from a Pages collection. The following example references the Message page and then references the CommandButton1 control on the page. When clicked, the CommandButton1 control moves to the right.

Important   The Page object is contained in the Microsoft Forms 2.0 Object Library. To view the methods and properties for the Page object, consult "Microsoft Forms Visual Basic Reference" in Microsoft Outlook Visual Basic Reference Help.

Sub CommandButton1_Click
    Set MyPage = GetInspector.ModifiedFormPages("Message")
    Set MyControl = MyPage.CommandButton1
    MyControl.Left = MyControl.Left + 20
End Sub

The Controls Collection Object

To access controls on Outlook forms, you use the Controls collection object. The Controls collection object contains the collection of controls on a form page. To access an individual control in the Controls collection, you use the index value of the control or the name of the control. The Controls collection object is contained in the Microsoft Forms 2.0 Object Library. This section discusses how to reference control collections and controls on a form.

Important   Open the Control object item in the VBScript Samples folder to work directly with this code in Outlook.

Methods of the Controls Collection Object

The Controls collection object offers a variety of methods that let you manipulate the controls on a form. For example, you can use the Move method to move all the controls on a page, or you can use the SendToBack method to send the controls in the Controls collection to the back layer of the page. You can use the Controls property to return the Controls collection from a Page object. Use Controls*(index),* where index is the name or index number, to return a control from a Controls collection.

Adding a control to the form page

You can use the Add method of the Controls collection object to add a control to the form. The following example uses the Add method to add a new CommandButton control to the ControlObject page:

Sub AddAControlToAPage _Click
    Set MyPage = GetInspector.ModifiedFormPages("Control Object")
    If MyPage.Controls.Count < 3 then
        Set MyControl = MyPage.Controls.Add("Forms.CommandButton.1")
        MyControl.Left = 18
        MyControl.Top = 150
        MyControl.Width = 175
        MyControl.Height = 20
        MyControl.Caption = "This is " & MyControl.Name
    Else
        MsgBox "You can only add one command button.", vbInformation
    End If
End Sub

More Info   For more information about using the Add method of the Controls collection object, see "Control Reference" in Microsoft Outlook Visual Basic Reference Help.

Controls Collection Object Properties

The Controls collection object provides only the Count property. With the Count property, you can use the For . . . Next statement to loop through the controls in a collection. The following example returns the collection of controls on the Controls collection object page. It then displays the name of each control contained on the page.

Sub ShowtheControlsCollectionCount_Click
    Set Page = Item.GetInspector.ModifiedFormPages("Control Object")
    Set MyControls = Page.Controls
    For i = 0 to MyControls.Count – 1
        MsgBox MyControls(i).Name, vbInformation
    Next
End Sub

Important   Notice that the For . . . Next statement starts at 0. You must use 0 to reference the first item in the collection. However, Outlook returns a Count of 3. Therefore, you must specify Count -1 as the upper limit in the argument of the For . . . Next statement.

The Control Object

In the Visual Basic Forms Object Model, the control objects are generically represented by a Control object. Further, they are individually represented by the objects that represent the names of the individual control components, such as TextBox, CheckBox, and so on. As discussed in the preceding section, to reference a control, use the Controls property to return the Controls collection from a Page object, and then use Controls*(index),* where index is the name or index number, to return a control from a Controls collection.

Important   The Control object and the individual control objects, such as CheckBox and TextBox, are contained in the Microsoft Forms 2.0 Object Library. To view the methods and properties for this library, use the VBA Object Browser and select MSForms in the library drop-down list box.

Unlike controls on VBA or Visual Basic forms, the control object in VBScript must be explicitly instantiated before you can access the properties and methods of the control. You must explicitly reference the control object regardless of whether the control is an intrinsic Outlook Forms control or an extrinsic custom or third-party ActiveX control. The following line of code shows you how to set a reference to a control object:

Set TextBox1 = 
  Item.GetInspector.ModifiedFormPages("P.2").Controls("TextBox1")

A shorter alternative syntax is as follows:

Set TextBox1 = GetInspector.ModifiedFormPages("P.2").TextBox1

Setting Control References at the Script Level

If you inspect the code behind the Control object example form, you'll see that some control objects have been dimensioned as script-level variables. The Item_Open procedure then sets a reference to each control dimensioned as a script-level variable, and the control object has a script-level lifetime. If you follow this convention, you do not have to instantiate a control object reference in every procedure where you want to get or set control properties and call control methods. Dimension the controls as script-level variables using the same name as the control, and then instantiate those control variables in the form's Item_Open procedure. Don't use an alias for the control object. Name the control object on the left side of the Set statement with the same name as the actual control. This practice makes your code more readable because the name of the control in VBScript code is the same as the control name in Design mode.

Properties of Control Objects

The properties available for a control will differ for each type of control. This section covers the Value property for the CheckBox control and the Enabled property for the TextBox and Label controls.

Setting the enabled property of a control

The following example uses a CheckBox control called EnableTextBox and a TextBox control called TextBox1. When the EnableTextBox control is clicked, the procedure evaluates the state of EnableTextBox. If the value of EnableTextBox is True, then TextBox1 and Label1 are enabled; otherwise, they are not enabled.

Sub EnableTextBox_Click
    Set MyPage = Item.GetInspector.ModifiedFormPages("Control Object")
    Set MyControls = MyPage.Controls
    If MyControls("EnableTextBox").Value = True then
        MyControls("Label1").Enabled = True
        MyControls("TextBox1").Enabled = True
    Else
        MyControls("TextBox1").Enabled = False
        MyControls("Label1").Enabled = False
    End If
End Sub

Setting the PossibleValues property of a ComboBox or ListBox control

Rather than use the AddItem method to add items to a ListBox or ComboBox control, you can use the PossibleValues property. Note that the PossibleValues property is an undocumented property. In this example, the PossibleValues property is used to add the values Red, Green, and Blue to the ComboBox1 control when CommandButton1 is clicked.

Sub CommandButton1_Click
    Set MyPage = Item.GetInspector.ModifiedFormPages("Message")
    MyPage.ComboBox1.PossibleValues = "Red;Green;Blue"
End Sub

Using the List property to populate a ListBox or ComboBox control

The most powerful method to add values to a ListBox or ComboBox control is the List property. The List property populates a ListBox control or ComboBox control with a single statement. By assigning the control object's List property to a variant array, you can create a single-column or a multi-column list in the control. If you are populating controls with the results of an ADO recordset, the List property and the recordset GetRows method (which returns a variant array) are perfect partners. The following example from the Item_Open event in the Control object form creates a variant array and then assigns the array to the List property of the ListBox1 and ComboBox1 controls:

Sub Item_Open
    'Instance script-level control objects
    Set ListBox1 = GetInspector.ModifiedFormPages _
        ("Control Click Events").ListBox1
    Set ComboBox1 = GetInspector.ModifiedFormPages_
        ("Control Click Events").ComboBox1
    'Create a variant array to hold values
    Redim varArray(2)
    varArray(0) = "Red"
    varArray(1) = "Blue"
    varArray(2) = "Green"
    'Populate ListBox1 and ComboBox1
    ListBox1.List = varArray
    ComboBox1.List = varArray
End Sub

Hiding columns in a ComboBox control

You can hide a column in a ComboBox control by using the ColumnWidths property. The following example presents a typical problem for the designer of a mutli-column combo box. You want to present recognizable names, such as the full name of a state, but you only want to store the state's abbreviation. The PopulateStates procedure in the Control object form populates the cmbStates combo box with the abbreviation and full name for several vacation states. The ColumnWidths property is set so that the state abbreviation does not appear in the drop-down portion of the list. However, the TextColumn property is set so that the abbreviation appears in the ComboBox control when the user selects an item from the list. If you are binding the control to a user-defined field, you should also set the BoundColumn property so that the bound field uses the specified column as its value source. The cmbStates_Click procedure utilizes the Text, ListIndex, and Column properties of the combo box to create a message box that informs the user about their selection.

Sub PopulateStates
    Dim varStates()
    Set cmbStates = _
        GetInspector.ModifiedFormPages("Control Object").cmbStates
    ReDim varStates(6,1)
    varStates (0,0) = "AZ"
    varStates (0,1) = "Arizona"
    varStates (1,0) = "CA"
    varStates (1,1) = "California"
    varStates (2,0) = "HI"
    varStates (2,1) = "Hawaii"
    varStates (3,0) = "ID"
    varStates (3,1) = "Idaho"
    varStates (4,0) = "NV"
    varStates (4,1) = "Nevada"
    varStates (5,0) = "OR"
    varStates (5,1) = "Oregon"
    varStates (6,0) = "WA"
    varStates (6,1) = "Washington"
    cmbStates.List = varStates
    cmbStates.ColumnCount = 2
    cmbStates.ColumnWidths = "0 in ; 1 in" 'Hide col 0
    cmbStates.TextColumn = 1
    cmbStates.BoundColumn = 1
End Sub
Sub cmbStates_Click
    MsgBox "You selected the state of " & cmbStates.Text _
        & vbCr & "Enjoy your vacation in " _
        & cmbStates.Column(1, cmbStates.ListIndex), vbInformation
End Sub

Tip   When you set TextColumn or BoundColumn in a ListBox or ComboBox control, remember that the Column property is zero-based so that Column 1 is referenced as Column(0).

Resizing a control vertically and horizontally

Quite often, you want controls on a form to adjust horizontally and vertically when the form is resized. To do this, you must set an invisible property called LayoutFlags. This example sets the LayoutFlags property for the TextBox1 control when you click CommandButton1.

To run the example, do the following:

  1. In Design mode, add a TextBox1 control to the (P.2) page of a form.
  2. Resize the control so that its bottom border is near the bottom border of the form and its right border is near the right border of the form. Don't obscure the CommandButton1 control.
  3. Add the following code for the CommandButton1 control.
  4. Switch to Run mode, resize the form, and notice what happens.
  5. Then click CommandButton1 and resize the form. After the LayoutFlags property is set, the controls adjust to the size of the form.
Sub CommandButton1_Click
    Item.GetInspector.ModifiedFormPages("P.2")
      .TextBox1.LayoutFlags = 68
End Sub

After you set the LayoutFlags property, you can delete the procedure from the Script Editor.

Resizing a control vertically

In some situations, you want controls on the form to vertically resize when the form is vertically resized. To do this, set the LayoutFlags property to 65.

To run this example, do the following:

  1. Delete the TextBox1 control from the (P.2) page, and then add a new TextBox1 control.
  2. Resize the control so that its bottom border is near the bottom border of the form. Don't obscure the CommandButton1 control.
  3. Add the following code for the CommandButton1 control.
  4. Switch to Run mode, and resize the form vertically. Then click CommandButton1, and vertically resize the form again.
Sub CommandButton1_Click
    Item.GetInspector.ModifiedFormPages _
        ("P.2").TextBox1.LayoutFlags = 65
End Sub

After you set the LayoutFlags property, you can delete the procedure from the Script Editor.

Binding a control to a field at run time

You can use the hidden ItemProperty property to bind a control to a field at run time. To run this example, do the following:

  1. Add a new TextBox1 control (or use the existing one if it's already on the form) to the (P.2) page of the form.
  2. Add the following code for the CommandButton1 control.
  3. Switch to Run mode, click the Message tab, and type Test in the Subject box.
  4. Then click CommandButton1. Notice that the value in the Subject box appears in the TextBox1 control because the control is now bound to the Subject field.
Sub CommandButton1_Click()
    Item.GetInspector.ModifiedFormPages _
        ("P.2").TextBox1.ItemProperty = "Subject"
End Sub

Note   If you create a control by dragging a plain text field to a form, you cannot bind the control to a field of a different type. For example, you cannot drag a TextBox control to a form and then bind it programmatically to a field containing an E-mail recipient type (such as the To field).

Binding a control to a data source

You can bind controls on an Outlook form to a data source with ADO. However, you should be cautious when incorporating non-Exchange sources of data into your solution. If your application requires online and offline use, dynamic connections to data with ADO are not practical in the offline state. You can use ADO persisted recordsets to store data in a folder and then extract that persisted recordset to the file system when you need to access the data. This practice is limited to small sets of data that do not change frequently. Figure 11-10 illustrates a form that populates unbound controls with data from a persisted recordset stored in an Outlook folder. For additional examples of bound data controls and other methods of retrieving data in Outlook, see the Data Access Strategies For Outlook folder under "5. Advanced Topics" in the "Building Microsoft Outlook 2002 Applications" personal folders (.pst) file.

Aa155615.odc_c11612730-10(en-us,office.10).gif

Figure 11-10. Bind controls to data with a persisted recordset stored in an Outlook folder.

Responding to the Click event

The Click event is the only event raised by controls on Outlook forms. You must define the Click event procedure for a control in the Script Editor as follows:

Sub ControlName_Click
    'Event code goes here
End Sub

The Click event fires without exception for the Label, Image, CommandButton, ToggleButton, and Frame controls. Open the Control object item in the VBScript Samples folder and click the Control Click Events page for a practical demonstration of control Click events. However, there are many exceptions to the Click event:

  • Right-clicking a control does not fire a Click event.
  • Not every third-party or custom ActiveX control will fire a Click event in the Outlook forms container.
  • The following controls do not respond to Click events in Outlook: TabStrip, SpinButton, ScrollBar, TextBox, and MultiPage.
  • The following controls only respond to Click events when they are populated with items and an item in the list is selected: ComboBox and ListBox.
  • The following controls respond to a Click event based on a change in their Value property: OptionButton and CheckBox.

An alternative to using a Click event is to write a CustomPropertyChange or PropertyChange event procedure for the bound field of the control. For example, the following procedure mimics the Buddy control available in Visual Basic by binding a SpinButton control to a user-defined field. When the user clicks the spin button, the value of TextBox2 changes. You can see this example in action on the page named "Using Control Values" in the Control Object item in the VBScript Samples folder.

Sub Item_CustomPropertyChange(ByVal Name)
Select Case Name
    Case "SpinButton2"
    TextBox2.Value = SpinButton2.Value
End Select
End Sub

The UserProperties Collection Object

The UserProperties collection object represents the custom fields contained in an item. To return a collection of user-defined fields for an item, you can use the UserProperties property of the MailItem object, the PostItem object, and so on. The UserProperty object represents a single field in the item.

**More Info **  For a complete list and description of the properties and methods for the UserProperties collection object, see Microsoft Outlook Visual Basic Reference Help.

Note   Standard properties in Outlook, such as Subject, To, and Body, are properties of the individual Item object. For more information, see "MailItem and PostItem Objects Properties" earlier in this chapter.

UserProperties Collection Object Methods

This section covers the Find method of the UserProperties collection object.

Getting and setting the value of a user property

You can use the Find method of the UserProperties collection object to get or set the value of a user-defined field in an item as follows:

MsgBox "The value of the Customer Name field is " _
    & Item.UserProperties.Find("Customer Name").Value & "."

The syntax, however, can be shortened by three dots to increase performance and readability. Because the Find method is the default method of the UserProperties object and the Value property is the default property of the UserProperty object, the following statement is equivalent to the one above:

MsgBox "The value of the Customer Name field is " _
    & UserProperties("Customer Name") & "."

To set the value of a UserProperty object, simply reverse the statement as follows:

UserProperties("Customer Name") = "Microsoft Corporation"

The ItemProperties Collection Object

The ItemProperties collection object is new to Outlook 2002. This object is related to the UserProperties collection object, which contains only custom properties defined for an Item. The ItemProperties object lets you enumerate all the properties available for an Item. Be aware that certain Item properties related to an AddressEntry object will display the Security Warning dialog box. The ItemProperties collection object contains child ItemProperty objects that provide additional information about the Item property. If you use the Add or Remove methods of the ItemProperties object, you can add or remove custom properties only. The following example enumerates all the default and user-defined properties for the Company form used in Chapter 12, "The Northwind Contact Management Application."

Sub EnumerateContactItemProps()
    Dim oContactItem As ContactItem
    Dim colItemProps As ItemProperties
    Dim i As Integer
    Dim strPath As String
    Dim oFolder As MAPIFolder
    On Error Resume Next
    strPath = "\\Public Folders\All Public Folders\" _
        & "Northwind Contact Management Application\Companies"
    Set oFolder = OpenMAPIFolder(strPath)
    Set oContactItem = oFolder.Items.Add("IPM.Contact.Company")
    Set colItemProps = oContactItem.ItemProperties
    For i = 0 To colItemProps.Count – 1
        Debug.Print colItemProps.Item(i).Name, _
            colItemProps.Item(i).Value, _
            colItemProps.Item(i).IsUserProperty
    Next
End Sub

The Recipients Collection Object

The Recipients collection object represents the names that appear in the To field of the MailItem, MeetingRequestItem, and TaskRequestItem objects.

Recipients Collection Object Methods

This section covers the Add and ResolveAll methods of the Recipients collection object.

More Info   For a complete list and description of the properties and methods for the Recipients collection object and the Recipient object, see Microsoft Outlook Visual Basic Reference Help.

Adding recipients to the collection

You can use the Add method of the Recipients collection object to add recipient names to the Recipients collection. The following example creates a new Message item and then uses the Recipients property of the MailItem object to return the Recipients collection object that, in this case, is empty. It then adds two names to the Recipients collection object, uses the ResolveAll method to resolve the recipient names, and then displays the Message form. For this example, you can replace the names Nancy Davolio and Michael Suyama with names of people in your organization.

Sub AddRecipientsToCollection_Click()
    Dim objItem As Outlook.MailItem
    Dim colRecips As Outlook.Recipients
    On Error Resume Next
    Set objItem = Application.CreateItem(olMailItem)
    If objItem Is Nothing Then
        MsgBox "Could not create MailItem.", vbCritical
        Exit Sub
    End If
    objItem.Subject = "Outlook Object Model"
    Set colRecips = objItem.Recipients
    If Err Then
        MsgBox "The User did not allow Address Book access.", _
          VbCritical
        Exit Sub
    End If
    colRecips.Add ("Nancy Davolio")
    colRecips.Add ("Michael Suyama")
    colRecips.ResolveAll
    objItem.Display
End Sub

Outlook Security   The AddRecipientsToCollection procedure will cause the Warning dialog box shown earlier in Figure 11-4 (on page 429) to display. Any access to the Recipients collection object displays the Warning dialog box. If you haven't used the Administrative form to access the Recipients object, you might need to know whether the user has pressed Yes or No to allow Address Book access. The previous code example traps an error on the Set colRecips = objItem.Recipients statement when the user clicks No in the Warning dialog box.

Automatically addressing an item to all contacts in a contacts folder

The following example uses the Add method and the ResolveAll method to show how you can use the Recipients collection object to create a procedure that allows you to automatically address a message to all the users in the Contacts folder in your Mailbox. In this procedure, the Contact's e-mail addresses are added to the Recipients collection object.

Sub AddresstoAllContacts_Click
    On Error Resume Next
    Set MyNameSpace = Application.GetNameSpace("MAPI")
    Set MyFolder = MyNameSpace.GetDefaultFolder(10)
    Set MyItems = MyFolder.Items
    Set MySendItem = Application.CreateItem(0)
    Set MyRecipients = MySendItem.Recipients
    For i = 1 To MyItems.Count
        If MyItems(i).EMail1Address <> "" Then
            MyRecipients.Add MyItems(i).EMail1Address
        End If
    Next
    MyRecipients.ResolveAll
    MySendItem.Display
End Sub

Automation

In addition to using VBScript or Visual Basic to program Outlook forms and COM Add-ins, you can use Visual Basic to program Outlook objects remotely. In order to enhance security, programs that automate Outlook externally will always be subject to the object model guards of the Outlook E-Mail Security Update. You use Automation when you want to control an entire session. For example, you may want to automatically send a message from within a Visual Basic or Microsoft Excel application.

To automate Outlook from another application, such as Visual Basic or Microsoft Excel, you must first reference the Microsoft Outlook 2002 Object Model. You can then use the GetObject function to automate a session that's already running, or the CreateObject function to open a new Outlook session. After the Outlook Application object is returned, you can then write code that uses the objects, properties, methods, and constants in the Outlook 2002 Object Model. The following example creates a Mail item from a Microsoft Excel 2002 worksheet when the MailSalesReport button is clicked:

Sub MailSalesReport_Click
    Set MyOlApp = CreateObject("Outlook.Application")
    Set MyItem = MyOlApp.CreateItem(olMailItem)
    MyItem.Subject = "Sales Results - " & Now()
    MyItem.Body = " Click the icon to open the Sales Results." &
      Chr(13)
    Set MyAttachments = MyItem.Attachments
    MyAttachments.Add "C:\My Documents\Q401.xls", OlByReference, 1, _
        "Q4 2001 Results Chart"
    MyItem.To = "Sales"
    MyItem.Display
End Sub

Note   As shown in the preceding example, the constants in the Outlook 2002 Object Model are valid when used in Visual Basic or Visual Basic for Applications.

Where To Go from Here

Microsoft Knowledge Base Articles Knowledge Base articles are available on the Web at http://support.microsoft.com/support. Also see "Using Visual Basic, VBA, or VBScript with Outlook (Chapter 11) KB Articles" in the Microsoft Web Sites folder under the Help And Web Sites folder on the companion CD.