Chapter 16. Debugging: Your Key to Successful Development

IN THIS CHAPTER

Why This Chapter Is Important

A good programmer is not necessarily one who can get things right the first time. To be fully effective as a Visual Basic for Applications (VBA) programmer, you need to master the art of debugging—the process of troubleshooting your application. Debugging involves locating and identifying problem areas within your code and is a mandatory step in the application-development process. Fortunately, the Access 2007 Visual Basic Editor (VBE) provides excellent tools to help you with the debugging process. Using the Access 2007 debugging tools, you can step through your code, setting watchpoints and breakpoints as needed.

Using the VBA debugging tools is significantly more efficient than taking random stabs at fixes to your application. A strong command of the Access 2007 debugging tools can save you hours of trial and error. In fact, it can be the difference between a successfully completed application-development process and one that continues indefinitely with problems left unsolved.

Avoiding Bugs

The best way to deal with bugs is to avoid them in the first place. Proper coding techniques can really aid you in this process. Using the Option Explicit statement, strong-typing, naming standards, and tight scoping can help you eliminate bugs in your code.

Option Explicit

Option Explicit requires that you declare all your variables before you use them. Including Option Explicit in each Form, Code, and Report module helps the VBA compiler find typos in the names of variables.

As discussed in detail in Chapter 8, “VBA: An Introduction,” the Option Explicit statement is a command that you can manually insert into the General Declarations section of any Code, Form, or Report module. If you prefer, you can have Access automatically insert the Option Explicit statement. To accomplish this, select Require Variable Declaration from the Editor tab after choosing Tools, Options from within the Visual Basic Editor. After you select that setting, Access inserts an Option Explicit statement in the General Declarations section of all new modules. This setting does not affect existing modules.

Strong-Typing

Chapter 8 covers the process of strong-typing your variables. Strong-typing a variable means indicating at declaration time the type of data you will store in a variable. For example, Dim intCounter As Integer initializes a variable that contains integers. If elsewhere in your code you assign a character string to intCounter, the compiler will catch the error.

Naming Standards

Naming standards can also go a long way toward helping you eliminate errors. The careful naming of variables makes your code easier to read and makes the intended use of the variable more obvious. Problem code tends to stand out when you have judiciously followed naming conventions. Chapter 1, “Access as a Development Tool,” covers naming standards. Appendix A, “Naming Conventions,” which is available for download at www.samspublishing.com, covers the details of naming standards.

Variable Scoping

Finally, giving your variables the narrowest scope possible reduces the chances of one piece of code accidentally overwriting a variable within another piece of code. You should use local variables whenever possible. Use module-level and global variables only when it is necessary to see the value of a variable from multiple subroutines or multiple modules. For more information about the issues surrounding variable scoping, see Chapter 8.

Bugs Happen!

Unfortunately, no matter what you do to prevent problems and errors, they still creep into your code. Probably the most insidious type of error is a logic error. A logic error is sneaky because it escapes the compiler; your code compiles but simply does not execute as planned. This type of error might become apparent when you receive a runtime error or when you don’t get the results you expected. In these cases, the debugger comes to the rescue.

Harnessing the Power of the Immediate Window

The Immediate window serves several purposes. It provides you with a great way to test VBA and user-defined functions, it enables you to inquire about and change the values of variables while your code is running, and it enables you to view the results of Debug.Print statements. To open the Immediate window while in the Visual Basic Editor, do one of three things:

  • Click the Immediate window tool on the Debug toolbar.
  • Choose View, Immediate window.
  • Press Ctrl+G.

Note

An advantage of pressing Ctrl+G is that this keystroke combination invokes the Immediate window without a Code window being active. You can click the Immediate window toolbar button or choose View, Immediate window only from within the VBE.


Figure 16.1 shows the Immediate window.

Figure 16.1. The Immediate window enables you to test functions and to inquire about and change the values of variables.

image


Note

The Debug tools are available on a separate toolbar. To show the Debug toolbar, right-click any toolbar or menu bar and select Debug from the list of available toolbars.


Testing Values of Variables and Properties

The Immediate window enables you to test the values of variables and properties as your code executes. This feature can be quite enlightening as to what is actually happening within your code.

To practice with the Immediate window, you do not even need to be executing code. To invoke the Immediate window while in a form, report, or module, press Ctrl+G. To see how this works, follow these steps:

  1. Run the frmClients form from the CHAP16EX.ACCDB database on the website.
  2. Press Ctrl+G to open and activate the Immediate window. Access places you in the VBE within the Immediate window.
  3. Type ?Forms!frmClients.txtClientID.Value and press Enter. The client ID of the current client appears on the next line.
  4. Type ?Forms!frmClients.txtCompanyName.Visible and press Enter. The word True appears on the next line, indicating that the control is visible.
  5. Type ?Forms!frmClients.txtContactTitle.BackColor and press Enter. The number associated with the BackColor of the Contact Title text box appears on the next line.

Your screen should look like the one shown in Figure 16.2. You can continue to request the values of properties or variables within your VBA code.

Figure 16.2. Use the Immediate window to test the values of properties.

image

Setting Values of Variables and Properties

You can not only display things in the Immediate window, but you also can use the Immediate window to modify the values of variables and controls as your code executes. This feature becomes even more valuable when you realize that you can re-execute code within a procedure after changing the value of a variable. Here’s how this process works:

  1. Invoke the Immediate window, if necessary. Remember that you can do this by pressing Ctrl+G.
  2. Type Forms!frmClients.txtContactTitle.Value = "Hello" in the Immediate window. Press Enter. The contact title of the current record changes to Hello.
  3. Type Forms!frmClients.txtIntroDate.Visible = False. Press Enter. Access hides the txtIntroDate control on the frmClients form.
  4. Type Forms!frmClients.txtClientID.BackColor = 123456. Press Enter. The background color of the txtClientID control on the frmClients form turns green. The Immediate window and your form now look like those shown in Figures 16.3 and 16.4, respectively.

    Figure 16.3. Set the values of properties using the Immediate window.

    image

Figure 16.4. The results of using the Immediate window to set the values of properties are shown here.

image

The Immediate window is an extremely valuable testing and debugging tool. The examples here barely begin to illustrate its power and flexibility.


Caution

Changes you make to data while working in the Immediate window are permanent. On the other hand, Access does not save changes you make to the properties of controls or the values of variables with the form or report.

Some people think that data changes made in the Immediate window are not permanent. In other words, if you modify the last name of a customer, they believe that the change will not be permanent (but, of course, it is). Other people think that if they change the BackColor property of a control, the change will persist in the design environment (but, of course, it won’t).


Clearing the Immediate Window

The Immediate window displays the last 200 lines of output. As you add additional lines of code to the Immediate window, older lines disappear. When you exit completely from Access, it clears the Immediate window. If you want to clear the Immediate window at any other time, follow these three steps:

  1. With the Immediate window active, press Ctrl+Home to go to the top of the Immediate window.
  2. Hold down your Shift key and press Ctrl+End to go to the last statement in the Immediate window.
  3. Press Delete.

Practicing with the Built-In Functions

In addition to being able to test and set the values of properties and variables using the Immediate window, you can test any VBA function. To do so, type the function and its arguments in the Immediate window, preceded by a question mark. This code returns the month of the current date, for example:

?datepart("m",date)

This code tells you the date one month after today’s date:

?dateadd("m",1,date)

This code tells you how many days exist between the current date and the end of the millennium:

?datediff("d",date(),#12/31/2999#)

Executing Subroutines, Functions, and Methods

In addition to enabling you to test any VBA function, the Immediate window lets you test any user-defined subroutine, function, or method. This is a great way to debug your user-defined procedures. To see how this works, follow these steps:

  1. Open the basExamples module found in the CHAP16EX.ACCDB database on the website.
  2. Invoke the Immediate window if it is not already visible.
  3. Type ?ReturnInitsFunc("Bill","Gates"). This calls the user-defined function ReturnInitsFunc, sending "Bill" as the first parameter and "Gates" as the second parameter. The value B.G. appears in the Immediate window. This is the return value from the function.
  4. Type Call ReturnInitsSub("Bill","Gates"). This calls the user-defined subroutine ReturnInitsSub, sending "Bill" as the first parameter and "Gates" as the second parameter. The value B.G. appears in a message box.

Notice the difference between how you call a function and how you call a subroutine. Because the function returns a value, you must call it using a question mark. On the other hand, when calling a subroutine, you use the Call keyword.


Note

You also can call a subroutine from the Immediate window by using this syntax:

RoutineName Parameter1, Parameter2, ....

Notice that, when you omit the Call keyword, you do not need to enclose the parameters in parentheses.


Printing to the Immediate Window at Runtime

The capability to print to the Immediate window is useful because you can test what is happening as your code executes without having to suspend code execution. It also is valuable to be able to print something to a window when you are testing, without interfering with the user-interface aspect of your code. You can test a form without being interrupted and then go back and view the values of variables and so on. Here’s how the process works:

  1. Type Call LoopThroughCollection in the Immediate window. This calls the user-defined subroutine LoopThroughCollection. The values Skating, Basketball, Hockey, and Skiing appear. The routine prints these values to the Immediate window.
  2. Open the frmDebugPrint form in Form view.
  3. Press Tab to move from the First Name field to the Last Name field.
  4. Press Tab to move back to the First Name field.
  5. Type your first name.
  6. Open the Immediate window. Notice that the routine sent all the statements to the Immediate window (see Figure 16.5). I coded these Debug.Print statements in all the appropriate form and control events.

    Figure 16.5. Use Debug.Print statements to print values to the Immediate window.

    image


Note

Although it is good practice to remove Debug.Print statements after you have completed the debugging process, you can safely deploy your applications without removing them. Your users will never know that the statements are in your code unless they view the Immediate window. The Debug.Print statements result in only a minor degradation in performance.


Invoking the Debugger

You can invoke the Access debugger in several ways:

  • Place a breakpoint in your code.
  • Place a watch in your code.
  • Press Ctrl+Break while the code is running.
  • Insert a Stop statement in your code.

A breakpoint is an unconditional point at which you want to suspend code execution. It is temporary because it is in effect only while the database is open. In other words, Access does not save breakpoints with the database.

A watch is a condition under which you want to suspend code execution. You might want to suspend code execution when a counter variable reaches a specific value, for example. A watch also is temporary; Access removes it after you close the database.

A Stop statement is permanent. In fact, if you forget to remove Stop statements from your code, your application stops execution while the user is running it.

Using Breakpoints to Troubleshoot

As mentioned, a breakpoint is a point at which Access will unconditionally halt the execution of code. You can set multiple breakpoints in your code. You can add and remove breakpoints as your code executes.

A breakpoint enables you to halt your code execution at a suspicious area of code. This way, you can examine everything that is going on at that point in your code execution. By strategically placing breakpoints in your code, you quickly can execute sections of code that you already debugged, stopping only at problem areas.

To set a breakpoint, follow these steps:

  1. Place your cursor on the line of code where you want to invoke the debugger.
  2. You can insert a breakpoint in one of four ways:

    • Press your F9 function key.

    • Click in the gray margin area to the left of the line of the code that will contain the breakpoint.

    • Click the Toggle Breakpoint button on the Debug toolbar.

    • Choose Debug, Toggle Breakpoint.

    The line of code containing the breakpoint appears in a different color, and a dot appears, indicating the breakpoint.

  3. Run the form, report, or module containing the breakpoint. VBA suspends execution just before executing the line of code where you placed the breakpoint. The statement that is about to execute appears in a contrasting color. (The default is yellow.)

Now that you have suspended your code, you can step through it one line at a time, change the value of variables, and view your call stack, among other things.

Keep in mind that a breakpoint is actually a toggle. If you want to remove a breakpoint, click in the gray margin area, press F9, or click Toggle Breakpoint on the Debug toolbar. Access removes breakpoints when you close the database, when you open another database, or when you exit Access.

The easiest way to get to know the debugger is to actually use it. The following example gives you hands-on experience in setting and stopping code execution at a breakpoint. The example is developed further later in the chapter.

Start by creating a form called frmDebug that contains a command button called cmdDebug. Give the button the caption Start Debug Process. Place the following code in the Click event of the command button:

image

Create a module called basFuncs. Enter three functions into the module:

image

Now you should debug. Start by placing a breakpoint within the Click event of cmdDebug on the line called Call Func1. Here are the steps:

  1. Click anywhere on the line of code that says Call Func1.
  2. Click in the gray margin area, press the F9 function key, click the Toggle Breakpoint button on the Debug toolbar, or choose Debug, Toggle Breakpoint. The line with the breakpoint turns a different color (red by default).
  3. Go into Form view and click the Start Debug Process button. Access suspends execution just before executing the line where you placed the breakpoint. VBA displays the line that reads Call Func1 in a different color (by default, yellow), indicating that it is about to execute that line (see Figure 16.6).

Figure 16.6. Code execution is halted at a breakpoint.

image

Stepping Through Code

Access 2007 gives you three main options for stepping through your code. Each one is slightly different. The Step Into option enables you to step through each line of code within a subroutine or function, whereas the Step Over option executes a procedure without stepping through each line of code within it. The Step Out option runs all code in nested procedures and then returns you to the procedure that called the line of code you are on. Knowing the right option to use to solve a particular problem is an acquired skill that comes with continued development experience.

Using Step Into

When you reach a breakpoint, you can continue executing your code one line at a time or continue execution until you reach another breakpoint. To step through your code one line at a time, click Step Into on the Debug toolbar, press F8, or choose Debug, Step Into.

The following example illustrates the process of stepping through your code, printing the values of variables to the Immediate window, and modifying the values of variables using the Immediate window.

You can continue the debug process from the breakpoint you set in the previous example. Step two times (press F8). You should find yourself within Func1, about to execute the line of code intTemp = 10 (see Figure 16.7). Notice that VBA did not stop on the line Dim intTemp As Integer. The debugger does not stop on variable declarations.

Figure 16.7. The Immediate window is halted within Func1.

image

The code is about to print the Debug statements to the Immediate window. Take a look by opening the Immediate window. None of your code has printed anything to the Immediate window yet. Press F8 (step) three more times until you have executed the line Debug.Print intTemp. Your screen should look like Figure 16.8. Notice the results of the Debug.Print statements.

Figure 16.8. The Immediate window shows entries generated by Debug.Print statements.

image

Now that you have seen how you can display variables and the results of expressions to the Immediate window, take a look at how you can use the Immediate window to modify values of variables and controls. Start by changing the value of intTemp. Click the Immediate window and type intTemp = 50. When you press Enter, you actually modify the value of intTemp. Type ?intTemp, and you’ll see that Access echoes back the value of 50. You also can see the value of intTemp in the Locals window. Notice in Figure 16.9 that the intTemp variable appears along with its value and type.

Figure 16.9. Here are the Immediate and Locals windows after modifying the value of intTemp.

image

Executing Until You Reach the Next Breakpoint

Suppose that you have reached a breakpoint, but you realize that your problem is farther down in the code execution. In fact, the problem is actually in a different function. You might not want to continue to move one step at a time down to the offending function. Use the Procedure drop-down menu to locate the questionable function, and then set a breakpoint on the line where you want to continue stepping. You now are ready to continue code execution until Access reaches this line. To do this, click Continue on the Debug toolbar, press F5, or choose Run, Continue. Your code continues to execute, stopping at the next breakpoint. To see how this works, continue the Debug process with the next example.


Note

You also can opt to resume code execution to the point at which your cursor is located. To do this, select Run to Cursor from the Debug menu, or press Ctrl+F8.


Suppose that you realize your problem might be in Func3. You do not want to continue to move one step at a time down to Func3. No problem. Use the Procedure drop-down menu to view Func3, as shown in Figure 16.10. Set a breakpoint on the line that reads Debug.Print "We Are Now In Func3()". You are ready to continue code execution until Access reaches this line. Click Continue on the Debug toolbar, press F5, or choose Run, Continue. Your code continues to execute, stopping on the breakpoint you just set. Press F5 again. The code finishes executing. Return to the Form View window.

Figure 16.10. Use the Procedure drop-down menu to view another function.

image

Using Step Over

Sometimes you already have a subroutine fully tested and debugged. You want to continue stepping through the routine that you are in, but you don’t want to watch the execution of subroutines. In this case, you use Step Over. To step over a subroutine or function, click Step Over on the Debug toolbar, press Shift+F8, or choose Debug, Step Over. The code within the subroutine or function you are stepping over executes, but you do not step through it. To experiment with the Step Over feature, follow the next example.

Click the open form and click the Start Debug Process button one more time. Because you did not remove the existing breakpoints, Access places you on the line of code that reads Call Func1. Select Clear All Breakpoints from the Debug menu or use the Ctrl+Shift+F9 keystroke combination to remove all breakpoints. Step (press F8) five times until you are about to execute the line Call Func2. Suppose that you have tested Func2 and Func3 and know that they are not the cause of the problems in your code. With Func2 highlighted as the next line Access will execute, click Step Over on the toolbar. Notice that Access executes Func2 and Func3, but that you now are ready to continue stepping in Func1. In this case, Access places you on the End Sub line immediately following the call to Func2.

Using Step Out

You use the Step Out feature to step out of the procedure you are in and to return to the procedure that called the line of code you are on. You use this feature when you have accidentally stepped into a procedure that you realize you have fully tested. You want to execute all the code called by the procedure you are in and then step out to the calling procedure so that you can continue with the debugging process. To test how this works, follow this example.

  1. Place a breakpoint on the call to Func2.
  2. Click the Reset button on the toolbar to halt code execution.
  3. Activate the frmDebug form and click the Start Debug Process command button.
  4. Step once to place yourself in the first line of Func2.
  5. Suppose that you realize you just stepped one step too far. You really intended to step over Func2 and all the procedures it calls. No problem! Click the Step Out button to step out of Func2 and return to the line following the line of code that called Func2. In this case, you should find yourself on the End Sub statement of Func1.

Setting the Next Statement to Execute

After you have stepped through your code, watched the logical flow, and modified some variables, you might want to re-execute the code beginning at a prior statement. The easiest way to do this is to click and drag the yellow arrow in the margin to the statement on which you want to continue execution. If you prefer, you can click anywhere in the line of code where you want to commence execution and then choose Debug, Set Next Statement. Regardless of the method you chose, notice that the contrasting color (usually yellow)—indicating the next line of code that Access will execute—is now placed over that statement. You then can step through the code by pressing F8, or you can continue normal code execution by pressing F5. Access enables you to set the next line it will execute within a procedure only. You can use this feature to re-execute lines of code or to skip over a problematic line of code.

The following example walks you through the process of changing the value of a variable and then re-executing code after you have changed the value.

The preceding example left you at the last line of code (the End Sub statement) within Func1. Now you want to change the value of intTemp and re-execute everything:

  1. Go to the Immediate window and type intTemp = 100.
  2. You need to set the next statement to print on the line that reads Debug.Print "We Are Now in Func1()". To do this, click and drag the yellow arrow from the End Sub statement to the Debug.Print "We Are Now In Func1()" line. Notice the contrasting color (yellow), indicating that that is the next statement of code Access will execute.
  3. Press F8 (step) two times. The code now executes with intTemp set to 100. Observe the Immediate window again. Notice how the results have changed.

Using the Call Stack Window

You have learned how to set breakpoints, step through and over code, use the Immediate window, set the next line to be executed, and continue to run until you reach the next breakpoint. When you reach a breakpoint, it often is important to see which functions the code called to bring you to this point. In this case, the Calls feature can help.

To bring up the Call Stack window, click the Call Stack button on the toolbar or choose View, Call Stack. The window in Figure 16.11 appears. If you want to see the line of code that called a particular function or subroutine, double-click that particular function or click the function and then click Show. Although Access does not move your execution point to the calling function or subroutine, you are able to view the code within the procedure. If you want to continue your code execution, press F8. You move back to the procedure through which you were stepping, and the next line of code executes. If you press F5, your code executes until it reaches another breakpoint or watch. If you want to return to where you were without executing additional lines of code, choose Debug, Show Next Statement.

Figure 16.11. You can view the stack with the Call Stack window.

image

To test this process, perform the next example:

  1. Click the Reset button to stop your code execution if you are still in Break mode.
  2. Remove the breakpoint on the call to Func2.
  3. Move to the procedure called Func3 in basFuncs. Set a breakpoint on the line Debug.Print "We Are Now in Func3()".
  4. Run the frmDebug form and click the command button. Access places you in Func3 on the line where you set the breakpoint.
  5. Bring up the Call Stack window by clicking the Call Stack button on the toolbar. If you want to see the line of code that called Func2 from Func1, double-click Func1. Although Access does not move your execution point to Func1, you are able to view the code within the procedure. To return to the next line of code to execute, choose Debug, Show Next Statement.
  6. Press F5, and the rest of your code executes.

Working with the Locals Window

The Locals window enables you to see all the variables on the current stack frame and to view and modify their values. To access the Locals pane, click Locals Window on the toolbar, or select Locals Window from the View menu. Three columns appear: Expression, Value, and Type. The Expression column shows you the variables, user-defined types, arrays, and other objects visible within the current procedure. The Value column displays the current value of a variable or expression. The Type column tells you what type of data a variable contains. The Locals windows displays variables that contain hierarchical information—arrays, for example—with an Expand/Collapse button.

The information contained within the Locals window is dynamic. Access automatically updates it as it executes your code and as you move from routine to routine. Figure 16.12 illustrates how you can use the Locals window to view the variables available with the Func2 subroutine. To try this example yourself, remove all existing breakpoints. Place a breakpoint in Func2 on the line of code that reads Debug.Print strName. Click Reset if you are still executing code, and click the Start Debug Process command button to execute code until the breakpoint. Click the Locals Window button on the Debug toolbar. Click the plus sign to view the contents of the public variable gintCounter.

Figure 16.12. You can use the Locals window to view the variables available within a subroutine.

image


Note

You can change the value of a variable in the Locals window, but you cannot change its name or type.


Working with Watch Expressions

Sometimes it is not enough to use the Immediate window to test the value of an expression or variable. You might want to keep a constant eye on the expression’s value. To do so, you can set a watch expression. After you add a watch expression, it appears in the Watch window. As you’ll see, you can create several types of watches.

Using Auto Data Tips

The quickest and easiest way to view the value contained within a variable is to use Auto Data Tips, which is an option for working with modules. This feature is available only when your code is in Break mode. While in Break mode, simply move your mouse pointer over the variable or expression whose value you want to check. A tip appears with the current value. To set the Auto Data Tips option from the VBE, choose Tools, Options, click the Editor tab, and check the option for Auto Data Tips, which is under the Code Settings options.

Using a Quick Watch

A quick watch is the most basic type of watch. To add a quick watch, highlight the name of the variable or expression you want to watch and click the Quick Watch button on the toolbar. The Quick Watch dialog box, shown in Figure 16.13, appears. You can click Add to add the expression as a permanent watch or choose Cancel to view the current value without adding it as a watch. If you click Add, the Watches window appears, like the one in Figure 16.14. The next section discusses this window in more detail.

Figure 16.13. The Quick Watch dialog box enables you to quickly view the value of a variable or add an expression as a permanent watch.

image

Figure 16.14. You can add a watch expression in the Watches window.

image

Adding a Watch Expression

As you saw, you can add a watch expression using a quick watch. Adding a watch this way does not give you full control over the nature of the watch, however. If you need more control over the watch, you must choose Debug, Add Watch. The Add Watch dialog box appears, as shown in Figure 16.15.

Figure 16.15. The Add Watch dialog box enables you to easily designate all the specifics of a watch expression.

image


Tip

If you add a quick watch or add a watch by choosing Debug, Add Watch, you easily can customize the specifics of the watch by clicking with the right mouse button over the watch in the Watches window. Then select Edit Watch.

A quick way to add a watch to the Watches window is to click and drag a variable or expression from a Code module into the Watches window. Access adds the watch with default settings.


In the Expression text box, enter a variable, property, function call, or any other valid expression. It is important to select the procedure and module in which you want to watch the expression. Next, indicate whether you want to simply watch the value of the expression in the Immediate window, break when the expression becomes True, or break whenever the value of the expression changes. The sections that follow cover the two latter options.

The next example walks you through the process of adding a watch and viewing the watch variable as you step through your code. It illustrates how a variable goes in and out of scope and changes value during code execution.

  1. To begin, stop code execution if your code is running and remove any breakpoints you have set.
  2. Click within the strName variable in Func2.
  3. Right-click and choose Add Watch.
  4. Click OK to accept the Func2 procedure as the context for the variable and basFuncs as the module for the variable.
  5. Set a breakpoint on the line strName = "Bill Gates".
  6. Run the frmDebug form and click the command button. View the Watches window and notice that strName has the value of a zero-length string.
  7. Step one time and notice that strName is equal to Bill Gates.
  8. Step three more times. Notice that, although you are in the Func3 routine, strName still has the value Bill Gates. The reason is that the variable is still in memory in the context of basFuncs.Func2.
  9. Step four more times until you are back on the End Sub statement of Func2. The strName variable is still in context.
  10. Step one more time. The strName variable is finally out of context because you have completed the execution of Func2.

Editing a Watch Expression

After you add a watch, you might want to edit the nature of the watch or remove it entirely. You use the Edit Watch dialog box to edit or delete a watch expression. Follow these steps:

  1. Activate the Watches window.
  2. Select the expression you want to edit.
  3. Choose Debug, Edit Watch, or right-click and choose Edit Watch. The dialog box in Figure 16.16 appears.

    Figure 16.16. You can use the Edit Watch dialog box to modify the specifics of a watch after you add it.

    image

  4. Make changes to the watch or click Delete to remove it.

Breaking When an Expression is True

A powerful aspect of a watch expression is that you can break whenever an expression becomes True. You can break whenever a Public variable reaches a specific value, for example. You might want to do this when a Public or Private variable somehow is being changed, and you want to find out where. Consider the following code, located in the basFuncs module of CHAP16EX.ACCDB:

image

You might find that gintCounter somehow is reaching a number greater than 100, and you are not sure how. To solve the problem, add the watch shown in Figure 16.17. Notice that the expression you are testing for is gintCounter > 100. You have set the breakpoint to break the code whenever the expression becomes True. To test the code, type ChangeGlobal1 in the Immediate window and press Enter. The code should break in the ChangeGlobal3 routine, indicating that this routine is the culprit.

Figure 16.17. This watch will cause the code execution to break whenever the expression is True.

image

Breaking When an Expression Changes

Instead of breaking when an expression becomes True, you might want to break whenever the value of the expression changes. This is a great way to identify the place where something is mysteriously modifying the value of a variable. Like Break When Value Is True, the Break When Value Changes option is great for tracking down problems with Public and Private variables. Notice the watch being set in Figure 16.18. It is in the context of all procedures within all modules. It is set to break whenever the value of gintCounter changes. If you execute the ChangeGlobal1 routine, you’ll find that the code halts execution within ChangeGlobal1 immediately after the code sets the value of gintCounter to 50. If you press F5 to continue execution, the code halts within ChangeGlobal2 immediately after it increments the value of gintCounter by 10. In other words, every time the code modifies the value of gintCounter, the code execution breaks.

Figure 16.18. This watch will cause code execution to break whenever the value of an expression changes.

image

Continuing Execution After a Runtime Error

As you are testing, you often discover runtime errors that are quite easy to fix. When a runtime error occurs, a dialog box similar to the one shown in Figure 16.19 appears.

Figure 16.19. You can fix runtime errors from the Runtime Error dialog box.

image

If you click Debug, Access places you in the Code window on the line that generated the error. After rectifying the problem, click the Continue button on the toolbar, or choose Run, Continue.

Figure 16.20 shows a divide-by-zero error, for example, after the user clicked Debug from the Runtime Error dialog box. The Locals window in the figure shows that the programmer set the value of int2 to 20. Code execution now can continue without error.

Figure 16.20. Here is the Debug mode after a divide-by-zero error.

image

Often, after an error occurs, VBA displays a message giving you the option of resetting your code. If you opt to reset your code, all variables (including Publics and Statics) lose their values. You also can click Reset on the toolbar. You must decide whether it is better to proceed with your variables already set or to reset the variables and then proceed.


Note

The General tab of the Options dialog box allows you to configure how VBA error handling and the debugger interact. Chapter 17, “Error Handling: Preparing for the Inevitable,” covers the options available to you.


Looking at Gotchas with the Immediate Window

Although the Access debugger is excellent, the debugging process itself is wrought with an array of potential problems, as follows:

  • The debugging process can interrupt code execution, especially when forms are involved. When this occurs, the best bet is to place Debug.Print statements in your code and examine what happens after the code executes.
  • Along the lines of the preceding problem, it is difficult to debug code where you have coded the GotFocus and LostFocus events. Moving to the VBE triggers the LostFocus event of the control. Returning to the form causes Access to trigger the GotFocus event of the control. Once again, a great solution is Debug.Print. You also might consider writing information to an error log for perusal after the code executes.
  • Code that uses Screen.ActiveForm and Screen.ActiveControl wreaks havoc on the debugging process. When the VBE is active, there is no active form and no active control. Avoiding these lines in your code wherever possible alleviates this problem.
  • Finally, be aware that resetting code can cause problems. If you are modifying environmental settings, you are left with whatever environmental settings your application code changed. If you continue execution after the error without resetting, all sorts of other problems can occur. It is a good idea to code a special utility routine that resets your environment.

Using Assertions

You use assertions to ensure that, if the user encounters a certain state, your code invokes the debugger. The following code, found in basExamples, is an example:

image

This example sets the value of a variable called intAge equal to the value entered into an Input Box. The Debug.Assert statement “asserts” that the value entered is greater than or equal to zero. If it is, code execution proceeds as expected. If the assertion is incorrect, the code invokes the debugger.

It is a good idea to include a comment as to why an assertion might fail. By doing this, you will facilitate the process of responding to the situation when it occurs. Also, it is important to realize that, if you deploy your application with Debug.Assert statements intact, you will receive a technical support call when an assertion fails, and your code places the user in the debugger without warning!

Debugging Tips

The following tips will make your life much easier when debugging:

  • Before starting to debug, be clear about what the problem is. Make sure that you get all the necessary information from the user as to what he did to generate the problem. Without this vital information, you can spend countless hours trying to reproduce the problem rather than solve it.
  • Make changes one line of code at a time. I have seen many hot-shot developers attempt to change multiple lines of code simultaneously. Instead of correcting the problem they initially set out to solve, they generate a multitude of additional problems.
  • Talk out the problem with other developers. Sometimes the process of simply verbalizing the problem can be enough to help you to figure it out. If verbalizing the problem doesn’t provide you with the answer, the person that you are verbalizing to might know the answer.
  • When all else fails, take a break. Many times I have stayed up into the wee hours of the night, attempting to solve a problem. After finally giving up, I surrender and go to bed. It’s amazing how many times I solve the “unsolvable” problem from the night before while in the shower the next morning!

Practical Examples: Debugging Real Applications

As you develop your own applications, use the techniques you learned to help solve any problems you encounter. For now, use the debugger to step through and learn more about the debugging process with one of the routines found in the sample database.

Summary

If programming were a perfect science, there would be no reason to use a debugger. Given the reality of the challenges of programming, a thorough understanding of the use of the debugger is imperative. Fortunately, the Access 2007 VBE provides an excellent tool to assist in the debugging process.

This chapter began by showing you how you can reduce the chance of bugs within your application in the first place. It then taught you how to use the Immediate window to test and change the values of variables and properties. You learned how to use watches and breakpoints, as well as how to view the call stack. All these techniques help make the process of testing and debugging your application a pleasant experience.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.61.73