Chapter 2 discussed events in a general way and showed you how to create your own events. Excel introduced real events to its object library in 1997, and they are one of the key improvements that allow Excel applications to be truly interactive with users.
The most obvious events occur for the Workbook
, Worksheet
, and Chart
objects since those objects include accompanying classes that you can view in the Visual Basic Editor (Figure 4-20).
You can list the events for Workbook
, Worksheet
, or Chart
objects by clicking on the object and event listboxes in the Code window, or you can refer to Table 4-7.
Table 4-7. Events available from Excel objects
Object |
Event |
---|---|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
You’ll notice that some of the same events occur for a number of objects. For example, the SheetActivate
event occurs for the Application
, Workbook
, Worksheet
, and Chart
objects (for Worksheet
and Chart
, it’s simply called the Activate
event). In this case, the Application
-level event is the most general event handler since it receives SheetActivate
events from all sheets in all open workbooks; the Workbook
-level event is next, receiving SheetActivate
events only from sheets in the open workbook; and the Worksheet-
or Chart
-level events are the most specific, receiving the Activate
event only from that specific Worksheet
or Chart
object.
Events occur at the most specific level first; then move up to more general levels. So, if the SheetActivate
event is handled at all three levels, the Worksheet
-level event procedure runs first, then the Workbook
-level event procedure, and finally the Application
-level procedure.
The object and event lists
are built in to the Code window for Workbook
and Worksheet
objects (Figure 4-20), but how do you use events for other objects, like Application
? To do so:
Declare a variable for the object using the
WithEvents
keyword.Initialize that object in code.
Visual Basic adds the object variable to the Code window’s object and event lists, which you can then use to add event procedures.
For example, the following code from the Workbook
class creates an object variable m_app
for the Application
object, initializes that object in the Workbook_Activate
event, then uses an Application
-level event:
Dim WithEvents m_app As Application ' (1) Private Sub Workbook_SheetActivate(ByVal Sh As Object) ' Initialize the object variable if it was not already. If m_app Is Nothing Then _ Set m_app = Application ' (2) ' Indicate the Workbook-level event occurred. MsgBox "Workbook-level event" End Sub Private Sub m_app_SheetActivate(ByVal Sh As Object) ' (3) ' Indicate the Application-level event occurred. MsgBox "App-level event" End Sub
The initialization step (previous) occurs in a Workbook
event so that it happens automatically. I could have placed it in the Workbook_Open
event, but that would have required me to close and reopen the workbook to see the code work. It’s easier to place the initialization step in an event that happens more frequently (such as SheetActivate
) and test if the variable has already been initialized with the If m_app Is Nothing
conditional statement.
Another interesting aspect of Excel events
are the Before
events, like BeforeRightClick
. It would be pretty neat if Excel really did know what the user was about to do, but that’s not quite how it works. Instead, the Before
events are simply processed after the user action, but before Excel does anything with them. That lets you intercept and (optionally) cancel Excel’s default action for those events. To see how this works, add the following code to the ThisWorkbook
class:
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, _ ByVal Target As Range, Cancel As Boolean) Dim ans As VbMsgBoxResult ans = MsgBox("Excel is about to process right-click, proceed?", vbYesNo) ' If no, then cancel the action. If ans = vbNo Then Cancel = True End Sub
Now, when you right-click on a sheet, you’ll see a message asking if the action should be processed. If you select Yes, Excel displays the sheet’s pop-up menu (that’s the default action for a right-click). If you select no, the menu is not displayed.
That’s a simple example that doesn’t do much, but Before
events are really pretty handy—for example, you can require that a user saves a workbook as shown by the following code:
Private Sub Workbook_BeforeClose(Cancel As Boolean) ' Require the user to save. If Not ThisWorkbook.Saved Then MsgBox "You must save this workbook before closing." Cancel = True End If End Sub
Try it!
Finally, you can turn Excel’s event processing off and on using the Application
object’s EnableEvents
property. Setting EnableEvents
to False
tells Excel to ignore any event procedures you’ve written in Visual Basic—the events still occur in Excel (so choosing File → Save saves the file, for instance) but none of your event procedures are run.
EnableEvents
affects only Excel events, so controls from the Microsoft Forms object library will still respond to events. You can see this by adding a checkbox to a worksheet and then writing the following code:
Private Sub chkEvents_Click( ) ' Turn off Excel events if checkbox cleared. Application.EnableEvents = chkEvents.Value End Sub
Get Programming Excel with VBA and .NET now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.