Friday, November 11, 2011

Item Events


Item Events

We've covered many of the application-level events available in Outlook 2002. Do you believe that you're ready to move to the head of the class yet? You can go beyond what you've learned so far and raise item-level events in addition to application-level events. You should be aware that Outlook 2000 introduced several new item-level events, including AttachmentAdd, AttachmentRead, BeforeAttachmentSave, and BeforeCheckNames. Outlook 2002 offers an additional item-level event: the BeforeDelete event. Following the convention established for application-level events, event names that begin with Before are subject to cancellation in the event procedure.
The important point about Outlook item-level events is that they can be controlled from ThisOutlookSession with Outlook VBA or from a COM Add-in created in Visual Basic or Visual C++. Outlook 97 and Outlook 98 did not support the declaration of item-level object variables using WithEvents in order to write event procedure code. Item-level event procedures were previously created using VBScript in Outlook custom forms. Many development projects will still require VBScript in Outlook forms. VBScript behind forms provides a simple means of enabling form-level automation and allowing that automation to travel from recipient to recipient.
In theory, an Outlook custom form could contain almost no VBScript code. The event-related behavior of this form could be controlled by item-level object variables that use Visual Basic code to create event procedures. The problem with this theoretical approach is that each client receiving your custom form would need to have your COM Add-in installed in order for the form's event procedures to function correctly. Portability of event automation is problematic when your code does not travel with the form itself. In a controlled corporate environment operating in conjunction with Exchange Server, the theoretical proposition of item-level event code residing in COM Add-in event procedures becomes more feasible if the correct COM Add-ins are deployed consistently to every client in the organization. In fact, this is one area of event automation that lends itself perfectly to COM Add-ins. If you want to create event procedures for default Outlook items such as a MailItem or ContactItem, you can do so without hesitation. A common complaint by Outlook developers is that a custom form cannot be substituted for the default mail message whose message class is IPM.Note. In Chapter 13, you'll learn how to make a custom form the default mail message in place of IPM.Note by changing registry settings. This ability constitutes a hidden feature of Outlook 2000 and Outlook 2002. If you don't want to resort to registry changes, you can create event procedure code that instantiates a MailItem object variable declared using WithEvents in the NewInspector event of the Inspectors collection object. You can use that MailItem object to write additional item-level event procedures.
The following example requires a subject to be entered for a message before the message is sent. If the user fails to enter a subject after the initial InputBox is displayed, the Send event is canceled. This code also requires chained event procedures to accomplish the intended result. All the required event procedures and declarations in the example have been included so that you can see how object variables and events are linked.
'Place these declarations in the general section of ThisOutlookSession
Public WithEvents colInsp As Outlook.Inspectors
Public WithEvents objMailItem As Outlook.MailItem

Private Sub Application_Startup()
    Set colInsp = Application.Inspectors
End Sub

Private Sub colInsp_NewInspector(ByVal Inspector As Inspector)
    Dim objItem As Object
    Set objInsp = Inspector
    On Error Resume Next
    Set objItem = objInsp.CurrentItem
    Select Case objItem.Class
        Case olMail
            Set objMailItem = objItem
    End Select
End Sub

Private Sub objMailItem_Send(Cancel As Boolean)
    If objMailItem.Subject = "" Then
       objMailItem.Subject = _
       InputBox("Enter a subject for this message:", "Subject Required")
       If objMailItem.Subject = "" Then
           Cancel = True
       End If
    End If
Exit Sub
This functionality could also be achieved by writing code for the ItemSend event of the Application object. However, the MailItem object has a much more granular event model. Using the previous example, you could write code for any one of the item-level events supported by the objMailItem object variable.

Adding Events to VBScript Behind Forms

By using the Script Editor, you can add code to an Outlook item event to modify the event's behavior. For example, for the Open event, you can add code to specify the current form page, or you can add code to load a ComboBox control with a recordset from a database. For the Click event, you can create a procedure that creates a custom item, includes an attachment to the current item, and then posts the item in a folder. Item events are available for all Outlook item types except for the NoteItem object. Certain events are cancelable; you can prevent them from completing by writing the appropriate code. The following table summarizes the item events in Outlook.
EventCancelableDescription
AttachmentAdd
No
Occurs when an attachment has been added to the item.
AttachmentRead
No
Occurs when an attachment has been opened for reading.
BeforeAttachmentSave
Yes
Occurs before an attachment in an item is saved.
BeforeCheckNames
Yes
Occurs before Outlook starts resolving names in the Recipients collection of the item.
BeforeDelete  (new to Outlook 2002)
Yes
Occurs before an item is deleted. This event will not fire unless the item is displayed in an Inspector.
Close
Yes
Occurs before Outlook closes the Inspector displaying the item.
CustomAction
Yes
Occurs before Outlook executes a custom action of an item.
CustomPropertyChange
No
Occurs when a custom item property has changed.
Forward
Yes
Occurs before Outlook executes the Forward action of an item.
Open
Yes
Occurs before Outlook opens an Inspector to display the item.
PropertyChange
No
Occurs when an item property has changed.
Read
No
Occurs when a user opens an item for editing.
Reply
Yes
Occurs before Outlook executes the Reply action of an item.
ReplyAll
Yes
Occurs before Outlook executes the Reply To All action of an item.
Send
Yes
Occurs before Outlook sends the item.
Write
Yes
Occurs before Outlook saves the item in a folder.

To add or modify an event

  1. With the form in Design mode, click View Code on the Form Design toolbar.
  2. On the Script Editor Script menu, click Event Handler.
  3. In the Insert Event Handler list box, double-click the event you want.
With an event procedure, the word item refers to the current Outlook item associated with the form. For example, the following Item_PropertyChangeprocedure sets the value of the Subject field in the item when the value in the Sensitivity drop-down list box in the Message Options dialog box is changed:
Sub Item_PropertyChange(ByVal PropertyName)
    Select Case PropertyName
    Case "Sensitivity"
        Item.Subject = "The sensitivity value has changed."
    End Select
End Sub
Item events are not raised exclusively at the item level in Outlook 2000 and Outlook 2002. A COM Add-in application event handler can also use the WithEvents declaration to raise item-level events and write item event procedure code in VBA or Visual Basic. However, if you want an event's code to travel with the form, you should use item-level event procedures written in VBScript.

The Firing Sequence of Events

When an Outlook form is opened to compose or read an item, events are fired in the sequences described in the following table.
EventWhen Fired
Open
A form is opened to compose an item.
Send, Write, Close
An item is sent.
Write, Close
An item is posted.
Write
An item is saved.
Close
An item is closed.
Read, Open
An item is opened in a folder.
Reply
A user replies to an item's sender.
ReplyAll
A user replies to an item's sender and all recipients.
Forward
The newly created item is passed to the procedure after the user selects the item's Forward action.
PropertyChange
One of the item's standard properties is changed.
CustomPropertyChange
One of the item's custom properties is changed.
CustomAction
A user-defined action is initiated.
AttachmentAdd
An attachment is added to a message. This event occurs before the BeforeAttachmentSave event (described below).
AttachmentRead
An attachment is read.
BeforeDelete
This event occurs before an item is deleted. The item must be open in an Inspector for this event to fire.
BeforeAttachmentSave
An attachment is saved in a message. This event occurs after the Send event and before the Write event.
BeforeCheckNames
Recipient names are resolved. This event occurs before the Send event.
An item's events fire whether the item is created through program code (in VBScript or VBA) or through the Outlook user interface.
The order in which Outlook calls event handlers might change depending on other events that can occur. The order might also change in future versions of Outlook.

Creating a New Item

When you create a new item, the Item_Open event is fired. In Outlook, you generally create a new item by opening a form. However, for certain folders, such as the Tasks folder, you can create a new item by clicking the New Item row in the folder. In either case, the Item_Open event is fired.

Sending an Item

When you send an item, the Item_Send event is fired, followed by the Item_Write event and then the Item_Close event.

Posting or Saving an Item

In Outlook, posting an item achieves the same result as saving an item. When you post or save an item, the Item_Write event is fired. An Item_Write event can occur in several situations. It can occur when a Post item is created and the Post button is clicked on the form, when a Contact item is created and the Save And Close button is clicked on the form, or when a Task item is created by clicking the New Item row and the item is then saved by the user clicking outside the New Item row. After the Item_Write event fires, the Item_Close event fires.

Opening an Existing Item

In Outlook, an item can be opened in two ways. If the item exists in a view that allows in-cell editing, simply clicking the item in the view will open it. An existing item can also be opened by double-clicking it and viewing it in a form. In either case, the Item_Read event is fired. If the item is viewed in a form, the Item_Read event is followed by the Item_Open event.
Sometimes you will not want the Item_Open event to fire when an item is opened by simply being clicked in a view with in-cell editing or by another process. Outlook does not provide an Item_New event. The following Item_Open procedure provides an escape hatch for exiting the procedure if the item is not new:
Sub Item_Open
    '1/1/4501 represents a date field with no value
    'If the item is not new, exit sub
    If Item.CreationTime <> #1/1/4501# Then
        Exit Sub
    End If
    'Continue Item_Open code here
End Sub

Closing an Item

When you close an item, the Item_Close event is fired. If changes have been made to the item, when you attempt to close the item, Outlook will ask if you want to save the changes. If you click Yes, the Item_Write event is fired, followed by the Item_Close event.

Preventing Events from Firing

In some cases, you might want to prevent events from occurring. For example, you might want to add code for a Reply event that opens a custom form rather than the default Message form. To achieve this functionality, you must first prevent the default behavior from occurring. To do so, assignFalse to the function value. The actual Event procedure must be declared as a Function procedure instead of a Sub procedure so that you can cancel an Item event with an Item_EventName = False statement.
VBScript and VBA use different syntax to cancel events. In VBScript code, you write the event procedure as a function and set the function value toFalse in order to cancel the event. In VBA or Visual Basic code, the event procedure contains a Cancel argument. Set the Cancel argument to True to cancel the event. The following VBScript example prevents the standard Reply event from occurring in a Mail Message form. Instead, it opens a custom Orders form when the Reply button is clicked.
Function Item_Reply(ByVal Response)
    Item_Reply = False
    Set MyFolder = Application.GetNameSpace("MAPI").GetDefaultFolder(6)
    Set MyItem = MyFolder.Items.Add("IPM.Note.Orders")
    MyItem.To = Item.To
    MyItem.Subject = "RE: " & MyItem.Subject
    MyItem.Display
End Function
The following example shows the same code located in an application-level event procedure in VBA. Unlike Outlook 97 and Outlook 98, Outlook 2002 allows you to raise events at the form level using the correct WithEvents declarations.
Public WithEvents objMailItem As Outlook.MailItem
'Additional code to instantiate objMailItem object as Inspector.CurrentItem
Private Sub objMailItem_ReplyAll(ByVal Response As Object, Cancel As Boolean)
    Cancel = True
    Set objFolder = _
        objApp.GetNameSpace("MAPI").GetDefaultFolder(olFolderInbox)
    Set objItem = objFolder.Items.Add("IPM.Note.Orders")
    objItem.To = objMailItem.To
    objItem.Subject = "RE: " & objItem.Subject
    objItem.Display
End Sub
Form-level events that can be canceled include the following:
  • Item_BeforeAttachmentSave
  • Item_BeforeCheckNames
  • Item_BeforeDelete
  • Item_Close
  • Item_CustomAction
  • Item_Forward
  • Item_Open
  • Item_Reply
  • Item_ReplyAll
  • Item_Send
  • Item_Write
Many other cancelable events are available at the application level. If you want to respond to application-level events, you must write VBA code in ThisOutlookSession or create a COM Add-in.

The AttachmentAdd Event

The AttachmentAdd event occurs when an attachment is added to an item either through a user action or by a procedure that uses code to add an Attachment object. The following VBScript example checks the size of the item after an embedded attachment has been added and displays a warning if the size exceeds 250,000 bytes:
Sub Item_AttachmentAdd(ByVal NewAttachment)
    Const olByValue = 1
    If NewAttachment.Type = olByValue Then
        If Item.Size > 250000 Then
        MsgBox "Warning: Item size is now " _
            & Item.Size & " bytes.", vbCritical
        End If
    End If
End Sub

The AttachmentRead Event

The AttachmentRead event occurs when an attachment in an item has been opened for reading. If the Attachment object is blocked by the Outlook E-Mail Security Update, the AttachmentRead event occurs after the Security Warning dialog box appears. The following example saves a copy of the attachment into the My Documents folder when the user opens that attachment:
Sub Item_AttachmentRead(ByVal ReadAttachment)
    Const olByValue = 1
    If ReadAttachment.Type = olByValue Then
    IntResponse = MsgBox("Save to c:\my documents?", vbQuestion + vbYesNo)
        If IntResponse = vbYes Then
            ReadAttachment.SaveAsFile "c:\my documents\" _
            & ReadAttachment.DisplayName
        End If
    End If
End Sub

The BeforeAttachmentSave Event

The BeforeAttachmentSave event occurs just after the Item_Send event and just before the Item_Write event. BeforeAttachmentSave always occurs after the AttachmentAdd event. This event is cancelable. If you're sending an item that contains an attachment and you cancel BeforeAttachmentSave, you will also cancel the Item_Write event. The following example prevents the user from saving an .exe file as an attachment:
Function Item_BeforeAttachmentSave(ByVal SaveAttachment)
    Const olByValue = 1
    If SaveAttachment.Type = olByValue Then
        If Instr(SaveAttachment.FileName, ".exe") Then
            MsgBox "Cannot save this attachment!", vbCritical
            Item_BeforeAttachmentSave = False
        End If
    End If
End Function

The BeforeCheckNames Event

The BeforeCheckNames event occurs just before Outlook starts to resolve names in an item's Recipient collection. This event will always fire before the Item_Send event fires. If you cancel the BeforeCheckNames event, the Item_Send event will also be canceled.

The BeforeDelete Event

The BeforeDelete event is new to Outlook 2002. It fulfills the need of developers searching for a means to handle item-level deletes. Be aware that an Inspector for the item must be open in order for the event to fire. If the user clicks the item in a view without opening it and then presses the Delete button, the BeforeDelete event will not fire. For a more reliable means to detect a Delete event in a folder, consider Exchange 5.5 scripting agents or Exchange 2000 event sinks.

The Click Event

The Click event occurs when a user clicks a control such as a command button on a form. You can create as many Click event procedures as there are controls on the form.
The Click event is the only VBScript control event supported in Outlook.

To create a Click event procedure

  • In the Script Editor, type the name of the control that you're creating the Click event for, followed by an underscore character (_) and the wordClick.
The following example creates an item and displays the standard Message form when CommandButton1 is clicked on the form:
Sub CommandButton1_Click  
  Set MyItem = Application.CreateItem(0)
  MyItem.Subject = "This is a test."
  MyItem.To = "Davide Atenoux"
  MyItem.Display
End Sub
For more information about the Click event, see "Responding to the Click Event" in Chapter 11.

The Close Event

The Close event occurs when the form associated with the item is being closed. When the Close event fires, the form is still open on the desktop. You can prevent the form from closing by setting the function value to False.

The CustomAction Event

The CustomAction event occurs when a custom action defined in the form occurs through code or a user action. You define custom actions on the Actions page of a form simply by creating a new action. When a CustomAction event is fired, both the name of the custom action being executed and the newly created response item are passed to the CustomAction event. You can prevent the custom action from occurring by setting the function value to False.
You can also use the CustomAction event as a custom method. For example, you can set the CustomAction event to False so that the response form is not loaded. You can then add code to the CustomAction event procedure to accomplish the desired task. For example, you can add code to the CustomAction event to automatically create an announcement message and send it to a distribution list.

The CustomPropertyChange Event

The CustomPropertyChange event occurs when the value in one of the item's user-defined fields changes. Because the field name is passed to the procedure, you can create a Select Case statement to determine which field value has changed.

The Forward Event

The Forward event occurs when the user initiates the Forward action on a form-usually by clicking the Forward button. You can prevent the form from being forwarded by setting the function value to False. In the following example, the Forward event is prevented from firing if the message is confidential:
Function Item_Forward(ByVal MyForwardItem)
    If Item.Sensitivity = 3 Then
        MsgBox "This message is confidential and cannot be forwarded.", _
            vbCritical
        Item_Forward = False
    End If
End Function

The Open Event

The Open event occurs when an Outlook form is opened to compose or read an item. When the Open event occurs, the form is initialized but not yet displayed. You can prevent the form from opening by setting the function value to False.
The example checks the ReceivedTime property of a message to determine whether the form is in Compose or Read mode. If the ReceivedTime property is not set, the Message page is shown. If the ReceivedTime property is set, the (P.2) page is shown so that the person processing the order can view it. Before you run this example, perform the following steps:
  1. Add a Message field to the (P.2) page.
  2. Add this example code in the Script Editor, and then click Publish Form As on the Form Design toolbar.
  3. In the Display Name text box, type TestEvent, and then publish the form to the Personal Forms Library.
  4. On the Outlook File menu, select New and then click Choose Form.
  5. Select the TestEvent form in the Personal Forms Library. Notice that the Message page is shown.
  6. Address the form to yourself, and click Send.
  7. Double-click the sent item in your Inbox. Notice that the (P.2) page is shown.
    Function Item_Open() 
        If Item.ReceivedTime <> "1/1/4501" Then
            Item.GetInspector.SetCurrentFormPage("P.2")\
            Item.GetInspector.HideFormPage("Message")
        Else 
            Item.GetInspector.SetCurrentFormPage("Message")
            Item.GetInspector.HideFormPage("P.2")
        End If
    End Function 
Note in the example that the If statement checks to see whether the ReceivedTime field is set to 1/1/4501. In Outlook, Date fields that display None will return a value of 1/1/4501.

The PropertyChange Event

The PropertyChange event occurs when one of the item's standard fields (such as Subject, To, Importance, or Sensitivity) changes. Because the field name is passed to the procedure, you can use the Select Case statement to determine which field value has changed.
In the following example, a message box shows the values of the Importance and Sensitivity fields that have changed. To see how it works, add the following code to the Script Editor. Then exit Design mode and change the values in the Importance and Sensitivity drop-down list boxes in the Message Options dialog box.
Sub Item_PropertyChange(ByVal FieldName)
    Select Case FieldName
    Case "Importance"
        MsgBox "The value of the Importance field is " _
            & Item.Importance & "."
    Case "Sensitivity"
        MsgBox "The value of the Sensitivity field is " _
            & Item.Sensitivity & "."
    End Select
End Sub

The Read Event

The Read event occurs when a user opens an existing Outlook item for editing. The Read event differs from the Open event in that it occurs whenever a user selects the item in a view that supports in-cell editing. The Read event also occurs when the item is being opened in an Inspector. This event is fired before the Open event. In the following example, the value of the Date Opened user-defined field is set when the submitted item is first opened.

Before you run this example, perform the following steps:

  1. Click New in the Field Chooser, and then type Date Opened in the Name text box.
  2. In the Type drop-down list box, click Date/Time and then click OK.
  3. Drag the Date Opened field to the Message page, and then click Edit Read Page on the Form Design toolbar.
  4. Resize the Message control to make room for the Date Opened control, and then drag the Date Opened field from the Field Chooser to the Read page.
  5. Click Publish Form As, and publish the form in your Personal Forms Library.
  6. On the Outlook File menu, select New, click Choose Form, and then select the form. Address the form to yourself, and click Send.
  7. Double-click the sent item in your Inbox. Notice that the current date is now in the Date Opened field.
    Function Item_Read()
        If UserProperties("Date Opened") = "1/1/4501" Then
            UserProperties("Date Opened") = Now
        End If
    End Function 

The Reply Event

The Reply event occurs when a user clicks the Reply button on the form. When this event occurs, the newly created Reply item is passed to the procedure. You can prevent the item from being sent by setting the function value to False. The following example prevents the standard Reply event from occurring and creates an item with a custom Task form. The code then copies the values from the item's Subject and To fields to the Task Response item.
Function Item_Reply(ByVal Response)
    Item_Reply = False
    Set MyFolder = Application.GetNameSpace("MAPI").GetDefaultFolder(13)
    Set MyItem = MyFolder.Items.Add("IPM.Task.Test")
    MyItem.To = Item.To
    MyItem.Subject = "RE: " & MyItem.Subject
    MyItem.Display
End Function

The ReplyAll Event

The ReplyAll event occurs when a user clicks the Reply To All button on a form. When a user clicks Reply To All, the response is sent to the sender as well as to all recipients in the To and Cc boxes on the form. You can prevent the item from being sent by setting the function value to False. The following example reminds the user that he or she is replying to all the original recipients of an item and allows the user to cancel the action:
Function Item_ReplyAll (ByVal MyResponse)
    MyResult = MsgBox("Do you really want to send this reply to all " _
        & "the recipients in the To and Cc boxes? ", _
        vbQuestion + vbYesNo + vbDefaultButton2, "Flame Protector")
    If MyResult = vbYes Then
        Item_ReplyAll = True
    Else
        Item_ReplyAll = False
    End If
End Function

The Send Event

The Send event occurs when a user sends an item. You can prevent the item from being sent by setting the function value to False. If you prevent this event from occurring, the form remains open. The following example automatically sets the expiration date on the item when it is sent:
Function Item_Send()
    Item.ExpiryTime = Date + 7
End Function

The Write Event

The Write event occurs when the user sends, posts, or saves an item. You can prevent an item from being saved by setting the function value to False. The following code prevents a form from changing its message class after either the HideFormPage or ShowFormPage method is called:
Function Item_Write
    Set objForm = Item.FormDescription
    Item.MessageClass = objForm.MessageClass
End Function

No comments:

Post a Comment