The Watch WindowThe Watch window is another amazingly multifunctional debugging tool provided by the VBE. Inexplicably, there is no direct keyboard shortcut available to display the Watch window. You can, however, use the standard Windows menu hotkey sequence Alt+V followed by an h character.The Watch window is typically used to display the value of variables or expressions that you have specified while you are stepping through your code in break mode. But the Watch window contains two features that make it invaluable as a run-time debugging tool as well: Break When Value Is True and Break When Value Changes. Both of these features are discussed at length later in this section. Unlike the Immediate window, the Watch window does not operate at design time. Setting a Basic WatchThe most fundamental feature of the Watch window is its capability to show you the value of a variable or expression that you specify in real time while you are stepping through your code. Adding a watch is very easy, but inexplicably, it is another fundamentally important operation involving the Watch window that has no keyboard shortcut. Therefore, the easiest way to add a watch is to highlight the variable or expression that you want to watch, right-click the highlighted area and choose Add Watch from the shortcut menu. The process of adding a watch is shown in Figure 16-10, Figure 16-11 and Figure 16-12. Figure 16-10. Specifying the Watch Expression[View full size image] ![]() Figure 16-11. Configuring the Watch Expression![]() Figure 16-12. The Completed Watch Expression[View full size image] ![]() Using a Basic WatchAs you step through your code in break mode, the Watch window will continually update the values of all of the watches you've added. This is the primary purpose of the Watch window. There are typically a large number of things going on in your code and the Watch window provides you with a method to monitor exactly what's happening to all of the critical variables and expressions in the code you're debugging.The Watch window enables you to modify the value of any variable or expression that is an lvalue. An lvalue is just a fancy computer science term that says the variable or expression can appear on the left side of an assignment. In the following line of code, for example, the expression Sheet1.Range("A1").Value is an lvalue because it is valid for this expression to appear on the left side of the assignment operation, which in this case assigns it the value of 25: By contrast, the expression ThisWorkbook.Worksheets.Count is not an lvalue because you cannot simply assign it a new value. It can only be changed by physically adding or removing worksheets in the workbook.To modify the value of an lvalue expression in the Watch window, just click the Watch window Value column in the row containing the value you want to modify. The Value column entry will turn into an editable field and you can type in a new value. The new value must be a data type that is valid for the expression you are altering. Figure 16-13 shows us changing the value of the expression Sheet1.Range("A1").Value to 99. Figure 16-13. Modifying the Value of a Watch Expression[View full size image] ![]() Watch TypesWhen you create a watch expression, you don't have to accept the default values of all the options in the Watch window. By modifying these defaults you can create watches that are much more powerful than those that simply use the default values.There are two option categories that you can modify when you add a watch: Watch Context and Watch Type. We cover them both in following sections. Don't worry if you don't get the values of these options correct when you first add the watch. You can edit any existing watch, which allows you to modify these options. The steps required to edit a watch are shown in Figure 16-14 and Figure 16-15. Figure 16-14. Right-Click over a Watch Expression to Edit It[View full size image] ![]() Figure 16-15. Change the Watch Type to Break When Value Changes![]() Watch ContextThe Watch Context options control the scope of the watch expression. Watches can be confined to code executing within a single procedure in a single module (the typical default) or they can apply to code executing anywhere within the project.Suppose, for example, you want to place a watch on a global variable or expression. If you simply add a watch on that variable or expression from within the first procedure where you come across it, the watch will only be valid when code is executing within the procedure where the watch was added. To change this, you change the selections in the two Watch Context drop-downs. ModuleWe are going to discuss the Watch Context options in reverse order of their appearance on the Watch dialog because the Module setting drives the Procedure setting. You have two options when selecting a Module setting: ProcedureThe Procedure setting determines what procedure the watch expression will be valid for within the module specified by the Module setting. As described above, if the Module setting value is (All Modules), then you have no choice over the Procedure setting. In this case, its only possible value will be (All Procedures). If a specific code module has been selected in the Module setting, there are two options for the Procedure setting:
Watch TypeThe Watch Type setting will determine how the Watch window handles the watch. The first option is passive, used only while stepping through code in break mode. The second two options are active and are used to initiate break mode. Watch ExpressionThis is the default value for the Watch Type setting. It just adds the specified variable or expression as a watch and displays its value while you are stepping through your code in break mode. Break When Value Is TrueThis Watch Type setting has much in common with the Excel conditional formatting expressions we discussed in Chapter 3 Excel and VBA Development Best Practices. When you specify this watch type, your watch is treated as a Boolean expression and code execution will stop and enter break mode whenever the value of the expression changes from False to True or <out of context> to True.This type of watch can be constructed as either a Boolean expression or a simple watch expression whose only possible values are True or False. Regardless of the way in which you construct the watch, code execution will stop and enter break mode whenever the value of the watch evaluates to True.One very common use for this Watch Type setting is somewhat counterintuitive but very valuable in practice. The Application. EnableEvents property is persistent from the time it is set to False until it is explicitly set to True or Excel is closed, which ever comes first. While this property is False, all Excel events are disabled. One of the most frequent Excel programming bugs is to set Application.EnableEvents to False and then forget to set it back to True when you no longer need to disable events. This will obviously cause havoc in any application that depends on trapping Excel events for its operation.We can very easily debug this problem by telling the Watch window to break code execution whenever the Application.EnableEvents property does not equal True. If the Application.EnableEvents property does not equal True, by definition it has been set to False. After you have set this watch, each time code execution breaks you know you have turned off Excel events. You can then examine the code that follows and ensure that Application.EnableEvents has been properly reset. We demonstrate setting this watch expression in Figure 16-16. Figure 16-16. Setting a Break When Value Is True Watch![]() Break When Value ChangesAnother common situation you want to watch for is when the value of an expression or variable in your code changes. In this case you are typically not concerned about the specific value to which your variable or expression changed, rather you want code execution to break whenever that value changes to anything other than its current value.This type of watch can be constructed as either a Boolean expression or a simple watch expression. Regardless of how you construct the watch, code execution will stop and enter break mode whenever the value of the expression changes. In Figure 16-17 we set a watch that will cause code execution to stop and enter break mode whenever the value of the expression Sheet1.Range("A1").Value changes. Figure 16-17. Setting a Break When Value Changes Expression![]() Arrays, UDTs and Classes in the Watch WindowSimple variables and expressions added to the Watch window are easy to understand on sight. But the Watch window is much more powerful than this. It can easily handle complex data types such as arrays, UDTs and classes. Watches for these data types are added in exactly the same way that watches for simple variables are added, but the results are quite different.Recall that in Chapter 13 Programming with Databases we created a BILLABLE_HOURS UDT to hold information about a billable hour entry from our timesheet application. Listing 16-5 shows a section of code from the PostTimeEntriesToDatabase procedure that uses this UDT. Listing 16-5. Code That Uses the BILLABLE_HOURS UDTLet's assume that we are debugging this code and we want to watch the contents of the BILLABLE_HOURS UDT. There's no need to add each individual element of the UDT to the Watch window. Just add a watch on the uData UDT variable as shown in Figure 16-18. Figure 16-18. Adding a Watch on a UDT Variable![]() Figure 16-19. Using a Watch on a UDT Variable[View full size image] ![]() Quick Watch (Shift+F9)The Quick Watch window is the little brother of the Watch window. By highlighting a variable or expression while in break mode and pressing Shift+F9, the Quick Watch window allows you to examine all the same details that would be displayed by the Watch window except for the data type. The Quick Watch window also allows you to quickly add the selected variable or expression to the Watch window by invoking the Add button (Alt+A). Figure 16-20 shows an example of the Quick Watch window being used to display the contents of a string variable. Figure 16-20. The Quick Watch Window![]() Figure 16-21. Tooltip Expression Evaluation![]() |