If you want to automate the way that Outlook works, you may sometimes need to write code that responds to Outlook events. Outlook has two classes of events, application-level events and item-level events, and between them, they enable you to write code that responds to most occurrences in Outlook. In this chapter, you will learn how to work with both types of events, and you will see code examples showing how to manage some of the events.
In addition to the events discussed in this chapter, Outlook supports form events such as those discussed in "Using Events to Control Forms" in Chapter 15, "Creating Complex Dialog Boxes."
And we'll conclude this chapter with a brief look at Outlook's Quick Steps feature. New in Outlook 2010, this tool is similar to Access's Macro Designer, though more limited. The Quick Steps dialog boxes allow you to cobble together actions that can later be executed, but without having to write any programming or record a formal macro. (Outlook doesn't have a Macro Recorder anyway.)
In this chapter you will learn to do the following:
Work with application-level events
Work with item-level events
Work with Outlook bar events
Understand the Quick Steps feature
By default, macros are disabled in Outlook 2010. To work with the examples in this chapter, or to use macros in general, you must select an enabling option in Outlook's Trust Center. To do so, follow these steps:
Click the File tab on the Ribbon.
Choose Options in the left pane of the File window.
Click Trust Center in the left pane of the Outlook Options dialog box.
Click the Trust Center Settings button.
Click Macro Settings in the left pane of the Trust Center dialog box.
Now choose one of the two lower options: Notification For All Macros (which gets old, fast) or Enable All Macros.
Recall that an event is something that happens to an object, such as a click, a mouse drag, a keystroke, and so on. You can write code in an event (an event procedure, as it's called) to respond to the click or other event.)
An application-level event is an event that happens to the Outlook application as a whole rather than to an individual item within it. For example, the Startup
event is an application-level event that occurs when Outlook starts, and the Quit
event is an application-level event that occurs when Outlook closes. By contrast, item-level events represent things that happen to individual items—for example, the opening of a particular email message or contact record or a user switching from one folder to another.
The application-level events are easier to access than the item-level events because the Application
object is the topmost object and is always available when Outlook is running. This means that you don't have to use an event handler to create the Application
object in the way that you have to create objects for the item-level events.
To access the application-level events, you use the ThisOutlookSession
class module. It's automatically inserted into the VBA Editor. Look in the Project Explorer and expand the Project1
item that represents the Outlook VBA project, then expand the Microsoft Outlook Objects
item. You now see the ThisOutlookSession
item. Double-click it to open a Code window showing its contents. (If this is the first time you've opened the ThisOutlookSession
class module, it will have no contents.)
Each of the events described in this section works with the Application
object. For simplicity, most of the following examples use the Outlook Application
object itself, but you could use an object variable that returns the Application
object instead.
Recall that you can find the Application
object in the drop-down list on the top left of the VBA Editor's Code window. All the events available to the Application
object can be selected from the drop-down list on the top right of the Code window, as shown in Figure 27.1:
You can select these various events from the drop-down list (causing the editor to type in the procedure structure for you) or just type the event name yourself as a Sub directly in the Code window. However, if you select from the drop-down list, the VBA Editor will automatically add any necessary arguments as well. Also, if you declare object variables using the WithEvents
statement, like this, the Editor's drop-down lists will include these objects and their available events:
Public WithEvents myInspectors As Inspectors Public WithEvents myInspector As Inspector
Figure 27.1. The drop-down list on the right shows all the events available in the Application
object.
That can be a useful shortcut while programming because you can view every event available in an object—and also have the editor type in the necessary arguments. Later in this chapter you'll experiment with the Inspectors
collection and the Inspector
argument.
The Startup
event, which takes no arguments, occurs when Outlook starts. In other words, every time the user starts Outlook, whatever code you might have written in the Sub Application_Startup()
procedure will automatically execute.
The Startup
event is useful for making sure that Outlook is correctly configured for the user to start work. The following example creates a new NoteItem
object (a note), assigns text to its Body
property, and uses the Display
item to display it:
Private Sub Application_Startup
()
Dim myNoteItem As NoteItem
Set myNoteItem = Application.CreateItem(ItemType:=olNoteItem)
myNoteItem.Body = "Please start a new time card for the day."
myNoteItem.Display
End Sub
The Quit
event occurs when Outlook is shut down. This event is triggered three ways:
By the user choosing Exit in the File tab of the Ribbon.
By the user clicking the red X icon in the upper right of the Outlook window.
By the programmer using the Quit
method of the Application
object in VBA.
When the Quit
event fires (is triggered), all windows have already been closed and all global variables have been released, so there's little left for a programmer to manipulate within this event procedure. One possibility, however, is to display a parting message to the user, as in the following example, which displays a message on the workday that precedes a national holiday to remind the user of the holiday:
Private Sub Application_Quit() Dim strMessage As String Select Case Format(Date, "MM/DD/YYYY") Case "01/18/2008" strMessage = "Next Monday is Martin Luther King Day." Case "02/15/2008" strMessage = "Next Monday is President's Day." Case "05/23/2008" strMessage = "Next Monday is Memorial Day." Case "07/03/2008" strMessage = "Friday is Independence Day." & _ " Monday is a company holiday." Case "08/29/2008" strMessage = "Next Monday is Labor Day." 'other National Holidays here End Select If strMessage = "" Then Exit Sub MsgBox strMessage, vbOKCancel + vbExclamation, "Don't Forget..." End Sub
The ItemSend
event occurs when an item is sent, either by the user issuing a Send
command (for example, by clicking the Send button in a message window) or by executing the Send
method in VBA code. The syntax for the ItemSend
event is as follows:
Sub expression
_ItemSend(ByVal Item As Object, Cancel As Boolean)
Here, expression
is a required expression that returns an Application
object. Item
is a required argument that specifies the item that's being sent. Cancel
is an optional Boolean argument that you can set to False
to prevent the item from being sent.
The following example examines the Subject
property of the Item
object being sent. If the Subject
property is an empty string, the message box prompts the user to add a subject line, and the Cancel = True
statement cancels the sending of the item:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean) If Item.Subject = "" Then MsgBox "Please add a subject line to this message." Cancel = True End If End Sub
The NewMail
event occurs when one or more new mail items arrives in the Inbox. The NewMail
event can be useful for sorting messages automatically. You can also specify custom rules to sort messages automatically. The NewMail
event takes no arguments.
The following example displays a message box that offers to show the Inbox when new mail arrives, triggering the NewMail event:
Private Sub Application_NewMail() If MsgBox("You have new mail. Do you want to see your Inbox?", _ vbYesNo + vbInformation, "New Mail Alert") = vbYes Then Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Display End If End Sub
The NewMailEx
event is a more complex version of the NewMail
event that passes to your code a list of the items received in the Inbox since the event last fired. The NewMailEx
event passes this list only for Exchange Server and other mailboxes that provide notification of messages received. The syntax is as follows:
Sub expression
.NewMailEx(EntryIDCollection As String)
Here, expression
is a required expression that returns an Application
object. EntryIDCollection
is a string that contains the entry IDs of the messages that have been received. Each entry ID is separated from the next by a comma; if there is a single entry ID, there is no comma in the EntryIDCollection
string.
The following example of a NewMailEx
event procedure uses a Do While... Loop
loop to separate the individual message IDs (by using the InStr
function to identify each section of the EntryIDCollection
string, up to the next comma, in turn). Then the code builds a string that contains introductory text followed by the subject line of each message, one message to a line. Finally, the procedure displays the string in a message box so that when Outlook receives new mail, the user receives an executive summary of the subject lines:
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String) Dim myMailItem As Object Dim intMsgIDStart As Integer, intMsgIDEnd As Integer
Dim intCutPoint As String, strMailItemID As String, strMailList As String intMsgIDStart = 1 intCutPoint = Len(EntryIDCollection) intMsgIDEnd = InStr(intMsgIDStart, EntryIDCollection, ",") strMailList = "You have the following messages:" Do While intMsgIDEnd <> 0 strMailItemID = Strings.Mid(EntryIDCollection, intMsgIDStart, _ (intMsgIDEnd - intMsgIDStart)) Set myMailItem = Application.Session.GetItemFromID(strMailItemID) strMailList = strMailList & vbCr & myMailItem.Subject intMsgIDStart = intMsgIDEnd + 1 intMsgIDEnd = InStr(intMsgIDStart, EntryIDCollection, ",") Loop MsgBox strMailList, vbOKOnly + vbInformation, "Mail Alert" End Sub
Outlook provides two events for working with advanced searches created using the AdvancedSearch
method. The AdvancedSearchComplete
event fires when the AdvancedSearch
method is run via VBA and finishes searching. The AdvancedSearchStopped
event fires when the AdvancedSearch
method is run via VBA and is stopped by using the Stop
method of the search.
The syntax for the AdvancedSearchComplete
event is as follows:
Private Sub expression
_ AdvancedSearchComplete(ByVal SearchObject As Object)
Here, expression
is a required expression that returns an Application
-type object variable that has been declared with events in a class module. SearchObject
is the Search
object that the AdvancedSearch
method returns.
The following example uses the AdvancedSearchComplete
event to return the number of search results that were found by the AdvancedSearch
method:
Private Sub Application_AdvancedSearchComplete(ByVal SearchObject As Search) MsgBox "The search has finished running and found " & _ SearchObject.Results.Count & " results.", vbOKOnly + vbInformation, _ "Advanced Search Complete Event" End Sub
The following example uses the AdvancedSearchStopped
event to inform the user that the search has been stopped:
Private Sub Application_AdvancedSearchStopped(ByVal SearchObject As Search) MsgBox "The search was stopped by a Stop command.", vbOKOnly End Sub
The MAPILogonComplete
event occurs when the user has successfully logged on to Outlook. You can use the MAPILogonComplete
event to ensure that Outlook is configured correctly for the user or simply to display an informational message. The MAPILogonComplete
event takes no arguments.
The following example of a MAPILogonComplete
procedure displays an informational message about current trading conditions when the user has successfully logged on to Outlook. The code includes a commented line indicating where the String variables strPubDownBegin
and strPubForecast
would be declared and assigned data in a full implementation:
Private Sub Application_MAPILogonComplete() Dim strMsg As String 'strPubDowBegin and strPubForecast declared and assigned strings here strMsg = "Welcome to the UltraBroker Trading System!" & vbCr & vbCr strMsg = strMsg & "Today's starting value is " & strPubDowBegin & "." _ & vbCr & vbCr strMsg = strMsg & "Today's trading forecast is " & strPubForecast & "." MsgBox strMsg, vbOKOnly + vbInformation, _ "UltraBroker Trading System Logon Greeting" End Sub
The Reminder
event fires immediately before the reminder for a meeting, task, or appointment is displayed to the user. You can use the Reminder
event to take an action related to the reminder. Because the reminder itself is usually adequate for reminding the user of the meeting, task, or appointment, the Reminder
event tends to be more useful when accessing Outlook programmatically than when working interactively with Outlook. The syntax is as follows:
Sub expression
_Reminder(ByVal Item As Object)
Here, expression
is a required expression that returns an Application
object, and Item
is the AppointmentItem, MailItem, ContactItem
, or TaskItem
object associated with the reminder.
The OptionsPagesAdd
event occurs when either the Options dialog box (Tools
Sub expression
_OptionsPagesAdd(ByVal Pages As PropertyPages, _
ByVal Folder As MAPIFolder)
Here, expression
is a required expression that returns an Application
object or a NameSpace
object. Pages
is a required argument that gives the collection of custom property pages added to the dialog box. Folder
is a required argument used when expression
returns a MAPIFolder
object. Folder
returns the MAPIFolder
object for which the Properties dialog box is being opened.
In addition to the application-level events discussed so far, Outlook supports a wide variety of item-level events—events that fire when items are manipulated rather than the application as a whole being affected.
You can handle item-level events in Outlook in two ways:
By declaring an event in a class module and running an initialization procedure so that VBA then traps the event when it fires. This chapter takes this approach.
By creating Visual Basic Script (VBScript) code and placing it in the form used by the item. This approach is especially useful for custom forms, but it is more limited than the previous approach because some of the events that Outlook supports are not available in VBScript. Script versions of computer languages were originally designed to execute when a user visits a web page. So these languages are supposed to contain fewer capabilities than ordinary languages. For example, VBScript doesn't have a command that deletes a folder in Outlook, whereas VBA does (FolderRemove
).
Follow these steps to declare an object variable and initialize an event:
Decide which class module to use for the declaration by using one of the following three methods:
To use the ThisOutlookSession
module, in the Project Explorer expand the project name (it's in boldface and by default is named Project1) that represents the Outlook VBA project, expand the Microsoft Outlook Objects item, and double-click the ThisOutlookSession
item to open a Code window showing its contents.
Create a class module by right-clicking the project name in the Project Explorer and choosing Insert
Open an existing class module by double-clicking it in the Project Explorer.
In the declarations area at the beginning of the class module (at the top of the Code window), declare a variable to represent the object to which the event applies. Use the WithEvents
keyword to declare that the object has events. The following example creates a public variable named myPublicContactItem
:
Public WithEvents
myPublicContactItem As ContactItem
Initialize the object variable by setting it to represent the appropriate object. The following example sets our myPublicContactItem
variable to represent the first item in the default contacts folder:
Set myPublicContactItem = Application.GetNamespace("MAPI") _ .GetDefaultFolder(olFolderContacts).Items(1)
Once you've initialized the object variable, the procedure will run after the event fires.
You can initialize the object variable manually if necessary, and you may find it convenient to do so when you're writing and testing code to handle events. But if you need to handle the event each time Outlook runs—if you want to make the macro a permanent part of your macro collection—it's obviously best to run the code to initialize the object variable automatically. For example, you might use the Startup
event of the Application
object (discussed in "Using the Startup
Event," earlier in this chapter) to run event-handling initialization code automatically each time Outlook starts.
Many of the item-level events apply to all the message items. Table 27.1 lists these events.
Table 27.1. Item-level events that apply to all message items
Event Occurs | Available in VBScript? | |
---|---|---|
| After an attachment is added to the item | Yes |
| When the user opens an email attachment for reading | Yes |
| When the user chooses to save an attachment but before the command is executed | Yes |
| Before Outlook checks the names of the recipients of an item being sent | Yes |
| Before an item is deleted | Yes |
| When an inspector is being closed but before the closing occurs | Yes |
| When the custom action of an item is executed | Yes |
| When a custom property of an item is changed | Yes |
| When the user forwards an item | Yes |
| When an item is opened in an inspector | Yes |
| When a standard property (as opposed to a custom property) in the item is changed | Yes |
| When an item is opened for editing in an inspector window or is selected for editing in-cell | Yes |
| When the user issues a | Yes |
| When the user issues a | Yes |
| When a | Yes |
| When an item is saved, either explicitly by the user or implicitly by Outlook | Yes |
Note that the Close
event applies to the Inspector
object and the Explorer
object as well as to the objects just mentioned.
The events that fire before an action occurs allow you to cancel the action so that it doesn't take place. The syntax for these events uses a Boolean argument named Cancel
that you can set to True
to prevent the action from taking place. For example, the syntax for the BeforeDelete
event is as follows:
Subexpression
_BeforeDelete(ByVal Item As Object,Cancel
As Boolean)
Here, expression
is a required expression that returns one of the message items to which the event applies (for example, a TaskItem
object). The following example uses the BeforeDelete
event to check that the TaskItem
object that's open in an inspector is marked as complete when the user tries to delete it. If the task is not marked as complete, a message box prompts the user to complete the task, and the example then sets the Cancel
argument to True
to prevent the deletion from occurring:
Private Sub myTaskItem_BeforeDelete(ByVal Item As Object, Cancel As Boolean)
If myTaskItem.Complete = False Then
MsgBox "Please complete the task before deleting it.", _
vbOKOnly + vbExclamation, "Task Is Incomplete"
Cancel = True
End If
End Sub
Table 27.2 lists the events that apply to explorers, inspectors, and views. Some events apply to both explorers and inspectors.
Table 27.2. Events that apply to explorers, inspectors, or views
Event | Applies To | Event Occurs | Available in VBScript? |
---|---|---|---|
| Explorer | Before the explorer displays a new folder | No |
| Explorer | When the user issues a | Yes |
| Explorer | When an item is cut from a folder | Yes |
| Explorer | Before an item is pasted | Yes |
| Explorer | Yes | |
| Explorer | After an explorer displays a new folder | No |
| Explorer | When the focus is moved to a different item in a folder, or when Outlook selects the first item in a folder when the user selects that folder | No |
| Explorer | When the view changes in the explorer window | No |
| Explorer, Inspector | When an explorer window or an inspector window is activated (becomes the active window) | No |
| Explorer, Inspector | When an explorer window or an inspector window is deactivated (stops being the active window) | No |
| Explorer, Inspector | When the user maximizes the explorer or inspector but before maximization takes place | Yes |
| Explorer, Inspector | When the user minimizes the explorer or inspector but before minimization takes place | Yes |
| Explorer, Inspector | When the user moves an explorer window or an inspector window but before the action takes place | Yes |
| Explorer, Inspector | When the user resizes the explorer or inspector but before the resizing takes place | Yes |
| Explorers | When a new explorer window is opened | No |
| Inspectors | When a new inspector window is opened | No |
| Views | When a view is added to the | Yes |
| Views | When a view is removed from the | Yes |
If you work on a small screen (for example, a laptop screen), you might prefer to use the NewInspector
event to maximize each inspector window you open and to hide any toolbars you don't need. The first procedure in the following example (which includes the necessary declarations) uses the NewInspector
event to make sure the Standard toolbar is displayed, hide the Advanced toolbar, and assign the Inspector
object representing the new inspector to the Public
object variable myInspector
. The second procedure uses the Activate
event of the myInspector
object to maximize its window by setting the WindowState
property to olMaximized
.
The net effect of these two event procedures is to configure the toolbars as described earlier and maximize the inspector window. The Activate
event procedure is necessary because the NewInspector
event runs before the inspector window is displayed, which means the NewInspector
event procedure cannot maximize the inspector window.
Public WithEvents myInspectors As Inspectors Public WithEvents myInspector As Inspector Private Sub myInspectors_NewInspector(ByVal Inspector As Outlook.Inspector) With Inspector With .CommandBars
.Item("Standard").Visible = True .Item("Advanced").Visible = False End With Set myInspector = Inspector End With End Sub Private Sub myInspector_Activate() myInspector.WindowState = olMaximized End Sub
Outlook provides three events (see Table 27.3) that apply to folders.
Table 27.4 lists the events that apply to items and results.
Table 27.4. Events that apply to items and results
Event | Event Occurs | Available in VBScript? |
---|---|---|
| When one or more items are added to the collection but not when many items are added all at once | No |
| When an item in the | No |
| When an item is deleted from the | No |
The example in the sidebar "How to Test Event Handler Procedures" employs the ItemChange
event to monitor when any contact is changed in the Contacts folder. After a change, the event procedure displays a message box asking if the user wants to inform colleagues of the change to the contact. If the user clicks the Yes button, the example creates and sends a message containing the vCard for the contact. The message goes to the Marketing Associates distribution list. Its subject is Contact details change:
and the name of the contact.
Outlook supports various events that apply to the Outlook bar (see Table 27.5). You may find these events useful if you need to customize the Outlook bar or constrain the user's navigation capabilities. For example, you can use the BeforeNavigate
event to check the shortcut to which the user is attempting to navigate. If the user is not permitted to access the folder associated with the shortcut, you can cancel the navigation.
Table 27.5. Events that apply to Outlook bar objects
Event | Applies To | Event Occurs | Available in VBScript? |
---|---|---|---|
|
| After a new group is added to the Shortcuts pane. | No |
|
| Before a new group is added to the Shortcuts pane. | No |
|
| Before a group is removed from the Shortcuts pane. | No |
|
| When a new group is opened in the Outlook bar. Does not fire in Outlook 2003 because Outlook 2003 has a different Navigation pane and Shortcuts pane. | No |
|
| After the user clicks a shortcut in the Shortcuts pane but before Outlook displays the folder represented by the shortcut. | No |
|
| Before a new shortcut is added to a group in the Shortcuts pane. | No |
|
| Before a shortcut is removed from a group in the Shortcuts pane. | No |
|
| After a new shortcut is added to a Shortcuts pane group. | No |
Table 27.6 explains the events that Outlook provides for reminders. You can use these events to take actions when a reminder fires, before the Reminder dialog box appears, when the user clicks the Snooze button to dismiss a reminder, or when reminders are added, changed, or removed.
Table 27.6. Events that apply to reminders
Event | Event Occurs | Available in VBScript? |
---|---|---|
| Before Outlook displays the Reminder dialog box | Yes |
| When a reminder is added | Yes |
| After a reminder has been changed | Yes |
| Before a reminder is executed | Yes |
| When a reminder is removed from the | Yes |
| When the user dismisses a reminder by clicking the Snooze button | Yes |
If you write procedures to synchronize Outlook, you may need to use the three events that apply to the SyncObject
object, which represents a Send/Receive group for a user. (You can access the SyncObject
object by using the SyncObjects
property of the NameSpace
object to return the SyncObjects
collection.) Table 27.7 explains the events that apply to the SyncObject
object.
The following example uses the OnError
event with the object variable mySyncObject
. If an error occurs during synchronization of the SyncObject
represented by mySyncObject
, the procedure displays an error message giving the error code and description:
Private Sub mySyncObject_OnError(ByVal Code As Long, _ ByVal Description As String) Dim strMessage As String
strMessage = "An error occurred during synchronization:" & vbCr & vbCr strMessage = strMessage & "Error code: " & Code & vbCr strMessage = strMessage & "Error description: " & Description MsgBox strMessage, vbOKOnly + vbExclamation, "Synchronization Error" End Sub
New in Outlook 2010, the Quick Steps feature allows non-programmers to combine actions in Outlook without having to record a macro (Outlook has no recorder) or write VBA programming.
While looking at the Mail page in Outlook, click the Home button on the Ribbon. You'll see the Quick Steps area right in the middle of the Ribbon.
The rationale for Quick Steps is quite similar to the rationale for writing or recording macros: After you've specified and saved a set of actions within a macro, you need not repeat those actions in the future—you merely run the macro and the behaviors are carried out automatically.
Quick Steps is similar to Access's Macro Designer: You're presented with a list of common actions and you can choose to combine two or more of them into a macro-like little "program." And, like a macro, a Quick Steps one-click button saves time by launching the "program" any time the user chooses. Non-programmers can build the Quick Steps "programs" out of actions that they frequently perform—thus saving time.
Although not nearly as flexible and powerful as writing macros in VBA, for a common task you might consider seeing if it's possible to create a Quick Step.
Some sample Quick Steps are already available in the Ribbon, and when you first click them you're asked to customize their behavior to suit your way of working. Click, for example, the MoveTo: ? sample and the First Time Setup dialog box opens, as shown in Figure 27.2.
Figure 27.2. Experiment with the sample Quick Steps to get an idea how to create and customize them.
As you see in Figure 27.2, you're allowed to customize this Quick Step by changing its name, specifying the target folder, and deciding whether or not to mark it as read. So this little program performs two actions at the click of a button. That could be a timesaver if you frequently store read email in a particular folder. Also notice the Options button where you can further modify the behavior of this Quick Step. You can add new actions, delete actions, specify a shortcut key, and write a tooltip.
Quick Steps makes 20 actions available to you, so it's no competition for the thousands of things you can do with VBA. Nonetheless, you might want to consider employing the Quick Steps feature for quick and easy automation of common mail-related tasks in Outlook.
Event handlers are procedures that contain code that responds to an event. In other words, if a user modifies one of their contacts, an event can detect this modification and execute code you've written to respond to the modification.
Event handler procedures are unlike ordinary macro procedures in several ways. Name one of the differences.
Outlook has two primary kinds of events.
What are the two types of events in Outlook? And how do they differ?
You can respond to user interaction with Outlook's bar by writing code in the bar's events.
Name one of the ways that Outlook's bar events can be employed by the developer.
18.119.159.178