VBA programs execute code-lines in a sequential manner. However, situations often arise where you need to skip ahead or circle back to a code-line. That is where jump statements like the GoTo statement come into play. They are of immense importance as they allow the non-sequential transfer of control (i.e., program execution).
Introducing the GoTo Statement
The Exit and Call statements transfer control from and into blocks or procedures. However, situations often arise where control needs to jump between lines in the same procedure. The GoTo statement is the circular peg for such round holes.
The GoTo statement unconditionally transfers control to any labelled statement in the same scope (i.e., procedure). After executing the labelled statement, control goes to the code-line immediately following it. The header image above illustrates its syntax and the flowchart below shows its logic flow.
Salient Points on Usage
There are several vital things to note about the GoTo statement:
- It must be in the same Sub, Function, or Property procedure as the labelled statement to which it transfers control;
- Sometimes the labelled statement appears after the GoTo statement. If so, control jumps forward, skipping any intermediate lines between the two statements. Clearly, this risks omitting critical lines, so take extra care to avoid that.
- Other times the labelled statement appears before the GoTo statement. If so, control jumps backward, repeating all lines between the two statements. Clearly, this risks an infinite loop, so pay due diligence to prevent that. That’s usually done by adding If or Select Case statements to execute an exit strategy.
- Due to the foregoing risks, the GoTo statement is widely regarded as a poor programming practice. Its lack of structure births errors. Besides, it also makes code more difficult to read and maintain.
Frankly, you should avoid using the GoTo statement as much as possible. It opens you up to errors and is not great for code readability. However, in a classic plot twist, it finds relevance in writing error handlers.
The GoTo Statement in Action
The sample code below shows the GoTo statement in use. It also illustrates the salient points discussed above.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Option Explicit Public Sub GoToStatement_Example01() 'demonstrating the GoTo statement's usage Dim byt_Tracker As Byte 'variable declaration line1: byt_Tracker = 2 'initialize tracker GoTo line3 'jump forward to the line labelled "line3" line2: 'double tracker's value & display result byt_Tracker = byt_Tracker * 2 Debug.Print "Tracker = " & CStr(byt_Tracker) 'to Immediate window Exit Sub 'following lines do not run line3: 'triple tracker's value & display result byt_Tracker = byt_Tracker * 3 Debug.Print "Tracker = " & CStr(byt_Tracker) 'to Immediate window 'notice absence of an "Exit Sub" statement, so following lines run GoTo line2 'jump back to the line labelled "line2" End Sub |
First, let’s ignore the GoTo and Exit Sub statements in the sample code above. In that case, the Sub procedure does the following:
- Declares a Byte variable, byt_Tracker, to hold a tracking number (code window line #7);
- Sets byt_Tracker’s value to ‘2’ in the labelled statement, line1 (line #9);
- Doubles byt_Tracker‘s value to ‘4’ (line #15);
- Prints the result to the Immediate window using the Debug.Print statement (line #16);
- Triples byt_Tracker‘s value to ‘12’ (line #21);
- Prints the result to the Immediate window using the Debug.Print statement (line #22).
Now, let’s see what happens when the GoTo and Exit Sub statements are active. In that case, the Sub procedure does the following:
- Declares a Byte variable, byt_Tracker, to hold a tracking number (line #7);
- Sets byt_Tracker’s value to ‘2’ in the labelled statement, line1 (line #9);
- The GoTo line3 statement (line #11) jumps control to the labelled statement, line3 (line #19);
- Triples byt_Tracker‘s value to ‘6’ (line #21);
- Prints the result to the Immediate window using the Debug.Print statement (line #22);
- Since there’s no Exit statement after line #22, control goes to the GoTo line2 statement in line #25. So, control then jumps to the series of lines starting at the labelled statement, line2 (line #13).
- Doubles byt_Tracker‘s value (i.e., ‘6’) to ‘12’ (line #15);
- Prints the result to the Immediate window using the Debug.Print statement (line #16);
- Since there’s an Exit statement after line #16, the Sub procedure ends immediately.
The importance of the Exit statement at the end of the labelled statement, line2, is clear. Without it, the series of lines starting at the labelled statement line3 would run again. Afterwards, the GoTo line2 statement would also run again. That would cause the series of code lines starting at the labelled statement, line2, to run again. The Ferris wheel (infinite loop) goes on forever!
Moreover, what happens if we remove the GoTo line2 statement, or place an Exit statement before it? Then the intended doubling of byt_Tracker‘s value never occurs. I imagine Yoda would say, “tricky construct, this statement is!“