Word Hacks [Electronic resources]

Andrew Savikas

نسخه متنی -صفحه : 162/ 100
نمايش فراداده

Hack 69 Hack with Application Events

Application events offer a powerful way to run VBA code when certain things happen within Word.

Windows is an events-based operating system. Most everything you do, from typing at the keyboard to scrolling within a window, triggers an event, which is then acted on by the program or the operating system.

Word exposes several events to you for use within your macros. For example, you can run a specific macro whenever the Word window is resized, or whenever the user right-clicks within a Word window.

If you have two Word documents open and you toggle between the two from the Window menu, three different events happen (in this order):

The WindowDeactivate event

The WindowActivate event

The DocumentChange event

At any of those stages (or all of them), you can specify VBA code to run every time that particular event "fires."

Application events fire when they occur anywhere within Word, not just within the document or template that contains the event-handling code. If your document (or the template on which your document is based) contains no macros, you can still work with events related to the document if you have defined event-handling code in your Normal template or in a currently loaded add-in.

A handy feature in Word 2002 and 2003 can help you remember to accept revisions or remove comments before you print or save a document. This hack will show you how to replicate this feature in earlier versions of Word.

7.14.1 Setting Up the Event Handler

For this hack, create a new template and name it Event Handlers.dot. Next, select ToolsMacroVisual Basic Editor, choose the Event Handlers.dot template in the Project Explorer, and then select InsertClass Module. The default name for a new class is Class1. Rename your class module EventHandler, as shown in Figure 7-16.

Figure 7-16. Renaming an inserted class module

Double-click the new EventHandler class to open it and insert this code:

Public WithEvents oThisWordApp As Application
Private Sub oThisWordApp_DocumentBeforePrint(ByVal Doc As Document, _
Cancel As Boolean)
Dim lResponse As Long
If Doc.Comments.Count <> 0 Or Doc.Revisions.Count <> 0 Then
lResponse = MsgBox(Chr(34) & Doc.Name & Chr(34) _
& " contains comments or tracked changes." & vbCr _
& "Continue with printing?", vbYesNo)
If lResponse = vbNo Then Cancel = True
End If
End Sub
Private Sub oThisWordApp_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, Cancel As Boolean)
Dim lResponse As Long
If Doc.Comments.Count <> 0 Or Doc.Revisions.Count <> 0 Then
lResponse = MsgBox(Chr(34) & Doc.Name & Chr(34) _
& " contains comments or tracked changes." & vbCr _
& "Continue with save?", vbYesNo)
If lResponse = vbNo Then Cancel = True
End If
End Sub

Notice that the two events that are handled, DocumentBeforePrint and DocumentBeforeSave, each take several arguments. Word will include these arguments as needed when you select an event that requires them. In the lefthand pull-down menu just above your code, select oWordApp. In the pull-down menu on the right, you can choose among the available application events. When you choose one, the appropriate shell code (sometimes called a "stub") is inserted, including any arguments, as shown in Figure 7-17.

Figure 7-17. Choosing from available application events

Now that you've created the class module that will handle the Word events, you need to create an instance of the class within a standard code module. To ensure that the event handler is activated as soon as the Event Handlers template is loaded, place the necessary code in an AutoMacro [Hack #60] .

Select the Event Handlers template in the Project Explorer and choose InsertCode Module. Insert the following code in the new module's declarations section. The declarations section is at the top of the code module, before any procedures.

Dim oEventHandler As New EventHandler

Below that declaration, insert the following code, which creates an instance of the EventHandler:

Sub AutoExec( )
Set oEventHandler.oThisWordApp = Word.Application
End Sub

7.14.2 Running the Hack

Save and close your Event Handlers.dot template. Next, select ToolsTemplates and Add-Ins and click the Add button to load it as a global template. As soon as Event Handlers.dot is loaded, whenever you save or print a document that contains comments or unaccepted revisions, you'll be prompted to confirm, as shown in Figure 7-18.

Figure 7-18. Using the DocumentBeforeSave event to warn if a document contains revisions or comments

Though similar to intercepting built-in commands [Hack #61], this event handler has two important differences.

First, the DocumentBeforeSave event fires when you choose either the Save or Save As commands. The other method forces you to intercept each separate command.

Secondand this is the biggiethe event handler will run even if you save the document from within a macro, making it an even more powerful and flexible technique than the command intercept.

If a macro tries to save a document and your event handler cancels the save, VBA may return an error. If you use event handlers, you need to include extra error handling in your macros.