This is the second in a series of articles that will dive into the behavior of the different Watch Types in VBA:
- Watch Expression
- Break When Value Is True
- Break When Value Changes
We'll focus on the second type in this article: Break When Value Is True. This type of Watch monitors the expression and halts code execution when the expression evaluates to True. In order to do this, it must evaluate the expression before executing every line of code. This has important implications when it comes to debugging performance.
To demonstrate the behavior of the different Watch Types, I'm going to use my own custom Watch() method to illustrate just how often these expressions are being evaluated.
Here's the sample code I will be using for the demonstration:
#If VBA7 Then Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) #Else Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) #End If Dim MyVar As Integer Function Watch(Val, Optional CalledFrom As String = "") Debug.Print Val, CalledFrom Sleep 1000 'Sleep for one second for demo purposes Watch = Val End Function Sub TestWatch() MyVar = 0 Debug.Print "Alpha" Debug.Print "Bravo" MyVar = 2 Debug.Print "Charlie" End Sub
Here's the expression I will be watching. Note that each time this expression is evaluated, the value of MyVar will be printed to the immediate window, along with the current date and time.
Watch(MyVar, Now) = 2
Throughout this series of articles, the code itself and the expression being watched will remain the same. The only things I will be changing are:
- the Watch Type
- the setting of breakpoints
- method of code execution (e.g., [F5] "Run" vs. [F8] "Step Into")
Watch Type: • Break When Value Is True
Run Sub [F5] - No Breakpoints - Expression False at the Start
In the first test, we're just running the test function using Run > Run Macro (F5). The initial value of MyVar is zero, which means the watched expression evaluates to False at the start.
Notice that VBA evaluates the expression before every single line of code and also every time that code execution halts.
There are six lines of code between
Sub TestWatch() and
Debug.Print "Charlie" (inclusive). However, the watched expression is evaluated seven times: once for each line of code and the seventh time when code execution halts (refer to image on left below).
After execution halts, I pressed [F5] a second time to continue running the routine. The expression was evaluated an eighth time before executing the
End Sub line and a ninth time when code execution stopped due to reaching the end of the routine.
Run Sub [F5] - No Breakpoints - Expression True at the Start
In the first test, the expression evaluated to False when we started. What happens if the evaluation is True at the beginning?
As it turns out, the behavior is identical to what we saw the first time through. Execution does not halt at the outset even though the expression starts out True. The code only stops executing when the expression evaluation changes from False to True:
Run Sub [F5] - No Breakpoints - Expression True Throughout
In the previous test, the expression evaluated to True when we started, but during execution we changed the value of MyVar so that the expression briefly evaluated to False. When we changed MyVar again so that the expression evaluated to True, VBA halted code execution.
What happens if the evaluation is True at the beginning and remains True throughout the entire course of code execution?
The answer? Code execution never halts. This means that the only way to get code execution to halt is for the expression to change from False to True.
Here are the key takeaways from the behavior of the "Break When Value Is True" Watch Type:
- VBA evaluates the watched expression before every line of code AND every time code execution halts
- VBA only breaks when the value CHANGES from False to True
- Since VBA evaluates the watched expression BEFORE executing the highlighted line of code, the line of code responsible for changing the watched expression from False to True is the PREVIOUS line