Error Handling using On Error


Errors are usually placed into three "categories"-compile time, run time, and logic. Compile-time errors are typically syntax errors such as missing double quotation marks that prevent your macro from compiling. Compile-time errors are the easiest to deal with because they are found immediately and the IDE shows you which line caused the problem. Run-time errors compile properly but cause an error when the macro runs. For example, dividing by a variable that at some point evaluates to zero will cause a run-time error. The third type, logic errors, are mistakes in the business logic of the program: They compile and run okay, but generate the wrong answers. They're the worst kind because you have to find them yourself-the computer won't help you at all. This section is about run-time errors: how to deal with them and how to correct them.

An error handler is a piece of code that runs when an error occurs. The default error handler displays an error message and stops the macro. OOo Basic provides a mechanism to modify this behavior (see Table 18 ). The first form, On Error Resume Next , tells OOo to ignore all errors: No matter what happens, keep running and pretend everything is fine. The second form, On Error GoTo 0, tells OOo to stop using the current error handler. Ignoring error handler scope issues, as explained later, think of On Error GoTo 0 as restoring the default method of handling errors: Stop running and display an error message. The final form, On Error GoTo LabelName, allows you to define code to handle errors the way that you want. This is called "setting up an error handler."

Table 18: Supported On Error forms.

Form

Usage

On Error Resume Next

Ignore errors and continue running at the next line in the macro.

On Error GoTo 0

Cancel the current error handler.

On Error GoTo LabelName

Transfer control to the specified label.

When an error occurs, the code that was running stops running, and control is transferred to the current error handler. The error handlers use the functions in Table 19 to determine the cause and location of the error.

Table 19: Error- related variables and functions.

Function

Use

Erl

Integer line number of the last error.

Err

Integer error number of the last error.

Error

Error message of the last error.

Compatibility  

Visual Basic uses an Error object and does not support the functions in Table 19 .

All error handlers must be declared in a routine and are local to the containing subroutine or function. When an error occurs, OOo Basic starts working backward through the call stack until it finds an error handler. If it doesn't find an error handler, it uses the default handler. The default handler prints an error message and halts the program. The error information, such as Erl, indicates the line number in the current routine that caused the error. For example, if the current routine calls the function b() at line 34 and an error occurs in b(), the error is reported as occurring at line 34. Listing 57 contains an example of this, and Figure 17 shows the call stack. Another example is shown in Listing 60.

click to expand
Figure 17: Walk the call stack to find a handler.
Listing 57: The error is cleared by the Resume Next statement.
start example
 x = x + 1                'Assume that this is line 33   Call b()                 'Error in b() or something b() calls (line 34)   Exit Sub                 'Leave the subroutine ErrorHandler:              'No other handlers between here and the error   Print "error at " & Erl  'Prints line 34 
end example
 
Tip  

Calls made to an external DLL will not generate an error that is catchable by an error handler. Check the return code from the called DLL instead.

Ignore Errors with On Error Resume Next

Error handling, in some cases, means ignoring errors. The On Error Resume statement tells OOo Basic that if a standard error occurs, it should ignore the error and resume running the code at the next line in the macro (see Listing 58 ). The error information is cleared, so it isn't possible to check if an error occurred following the statement.

Listing 58: The error is cleared by the Resume Next statement.
start example
 Private zero% sub ExampleErrorResumeNext   On Error Resume Next   Print 1/Zero%   If Err <> 0 Then Print Error$ & " at line " & Erl 'Err was cleared End Sub 
end example
 

Clear an Error Handler with On Error GoTo 0

Use the statement On Error GoTo 0 to clear an installed error handler. This is usually done inside an error handler or after the code that used one. If an error occurs inside an error handler, it isn't handled and the macro stops. See Listing 59 .

Listing 59: The error handler is cleared with the statement On Error GoTo 0.
start example
 Private zero% sub ExampleErrorResumeNext   On Error Resume Next   Print 1/Zero%   On Error GoTo 0   ... End Sub 
end example
 
Compatibility  

Some versions of Visual Basic also support On Error GoTo -1, which functions the same as On Error GoTo 0.

Specify Your Own Error Handler with On Error GoTo Label

To specify your own error handler, use On Error GoTo Label. To define a label in OOo Basic, type some text on a line by itself and follow it with a colon . Line labels are no longer required to be unique; they must only be unique within each routine. This allows for consistency in naming error-handling routines rather than creating a unique name for every error handler (see Listing 60 and Figure 18 ). When an error occurs, execution is transferred to the label.

click to expand
Figure 18: The last error handler declared is used.
Listing 60: ExampleJumpErrorHandler is found in the ErrorHandler module in this chapter's source code files as SC02.sxw.
start example
 Private zero% Private error_s$ Sub ExampleJumpErrorHandler   On Error GoTo ErrorHandler   JumpErrorl   JumpError2   Print 1/Zero%   MsgBox error_s, 0, "Jump Error Handler"   Exit Sub ErrorHandler:   error_s = error_s & "Error in MainJumpErrorHandler at line " & Erl() &_         " : " & Error() & CHR$(10)   Resume Next End Sub Sub JumpErrorl   REM Causes a jump to the handler in ExampleJumpErrorHandler.   REM The main error handler indicates that the error location is   REM at the call to JumpErrorl and not in JumpError1.   Print 1/zero%   error_s = error_s & "Hey, I am in JumpError1" & CHR$(10) End Sub Sub JumpError2   On Error GoTo ErrorHandler   Print 1/zero%   Exit Sub ErrorHandler:   error_s = error_s & "Error in JumpError2 at line " & Erl() &_         " : " & Error() & CHR$(10)   Resume Next End Sub 
end example
 

A routine can contain several On Error statements. Each On Error statement can treat errors differently. The error handlers in Listing 60 all used Resume Next to ignore the error and continue execution at the line following the error. Using multiple error handlers, it is possible to skip sections of code when an error occurs (see Listing 61 ).

Listing 61: Skip sections of code when an error occurs.
start example
 On Error GoTo PropertiesDone     'Ignore any errors in this section.   a() = getProperties()            'If unable to get properties then   DisplayStuff(a(), "Properties")  'an error will prevent getting here. PropertiesDone:   On Error GoTo MethodsDone        'Ignore any errors in this section.   a() = getMethods()   DisplayStuff(a(), "Methods") MethodsDone:   On Error Goto 0                  'Turn off current error handlers. 
end example
 
Bug  

The help included with OOo incorrectly states that error handling must occur at the start of a routine.

When you write an error handler, you must decide how to handle errors. The functions in Table 19 are used to diagnose errors and to display or log error messages. There is also the question of flow control. Here are some error-handling guidelines:

  • Exit the subroutine or function using Exit Sub or Exit Function.

  • Let the macro continue to run and ignore the error (see Listing 61).

  • Use Resume Next to continue running the macro at the line following the error (see Listing 62 and Figure 19 ).

    Listing 62: ExampleResumeHandler is found in the ErrorHandler module in this chapter's source code files as SC02.sxw.

    start example
     Sub ExampleResumeHandler   Dim s$, z%   On Error GoTo Handler1                'Add a message, then resume to Spot1   s = "(0) 1/z = " & 1/z & CHR$(10)     'Divide by zero, so jump to Handler1 Spot1:                                  'Got here from Handler1   On Error GoTo Handler2                'Handler2 uses resume   s = s & "(1) 1/z = "&1/z & CHR$(10)   'Fail the first time, work the second   On Error GoTo Handler3                'Handler3 resumes the next line   z = 0                                 'Allow for division by zero again   s = s & "(2) 1/z = "&1/z & CHR$(10)   'Fail and call Handler3 MsgBox s, 0, "Resume Handler" Exit Sub Handler1:   s = s & "Handler1 called from line " & Erl() & CHR$(10)   Resume Spot1 Handler2:   s = s & "Handler2 called from line " & Erl() & CHR$(10)   z = 1   'Fix the error then do the line again   Resume Handler3:   s = s & "Handler3 called from line " & Erl() & CHR$(10)   Resume Next End Sub 
    end example
     
  • Use Resume to run the same statement again. If the problem is not fixed, the error will occur again. This will cause an infinite loop (see Listing 62).

  • Use Resume LabelName to continue running at some specified location (see Listing 62).


Figure 19: The last error handler declared is used.
Note  

Errors that occur in an error handler are not handled; the macro just stops running.

Error Handlers-Why Use Them?

When I run a macro and it crashes, I usually understand the sometimes cryptic error messages and recognize how to deal with them. When others run my macros and an error occurs, I usually hear about it because they don't know how to handle it. This is a good indicator that I have not used proper error handling.

Tip  

You do not have to write an error handler for each routine. If the current routine doesn't have an error handler, but the routine that called it does, the caller's error handler is called. For example, imagine that sub 1 has an error handler and it calls sub2 that does not. If an error occurs in sub2, the error handler in sub1 is called.

When you use an error handler, you control how and when a user is notified of an error. Error handlers have uses other than controlling when a user is informed of an error. A properly used error handler can reduce the size of your macro. Consider, for example, the mathematical operations. It is cumbersome to check every mathematical operation before it is used.

 If x <> 0 Then y = z / x If x > 0 Then y = Log(x) If i% < 32767 Then i% = i% + 1 

Even with my paranoid code checking the parameters, I might still have a numeric overflow. Even worse , nothing is done if an error occurs, and processing continues as normal. Sometimes you can't check anything to avoid the error. For example, the DimArray function returns an invalid empty array. The LBound and UBound functions generate exceptions with these invalid empty arrays. You can write a function to safely generate the LBound and UBound even if an error occurs. Consider the following cases:

  • The argument is not an array.

  • In an empty array, UBound < LBound; -1 and 0, for example.

  • There are no problems if the array is not an invalid empty array.

  • Should the optional dimension be considered ?

The code in Listing 63 demonstrates a simple error handler that is able to simply ignore errors. The function returns True if the lower bound is less than or equal to the upper bound-in other words, if the array contains data. If an error occurs, either because the argument is not an array or because this is an invalid empty array, the line does not finish running so the assignment never takes place. If the assignment never takes place, the original default Boolean value of False is used. This is the correct answer. Writing a safe upper-bound or lower-bound routine is left as an exercise for the reader-the safe versions will not be required when the fixed Ubound and Lbound functions are released, probably in OOo 2.0.

Listing 63: ArrayHasStuff is found in the ErrorHandler module in this chapter's source code files as SC02.sxw.
start example
 Sub ExampleArrayHasStuff   Dim a() , b(3), v   Print ArrayHasStuff(a())        'False, because empty   Print ArrayHasStuff(v)          'False, not an array, so use error handler   Print ArrayHasStuff(DimArray()) 'False, bad array, so error handler called   Print ArrayHasStuff(DimArray(3))'True,  this is not empty   Print ArrayHasStuff(b())        'True,  this is not empty End Sub Function ArrayHasStuff(v) As Boolean   REM default value for a Boolean is False, so the default answer is False   REM If an error occurs, then the statement never completes!   REM This is a good time to use On Error Resume Next   On Error Resume Next   ArrayHasStuff = CBool(LBound(v) <= UBound(v)) End Function 
end example
 

An error handler can even be interactive. The code in Listing 64 attempts to copy a file that doesn't exist to a location that doesn't exist. Needless to say, an error is generated. An error message is displayed and the user is asked if the copy should be tried again. The user is given an opportunity to correct any errors and continue.

Listing 64: CopyAFile is found in the ErrorHandler module in this chapter's source code files as SC02.sxw.
start example
 Sub ExampleCopyAFile()   CopyAFile("/I/do/not/exist.txt", "/neither/do/I.txt") End Sub Sub CopyAFile(Src$, Dest$)   On Error GoTo BadCopy:     'Set up the error handler   FileCopy(Src$, Dest$)      'Generate the error AllDone:                     'If no error, then continue here   Exit Sub                   'Resume to the AllDone label from the handler BadCopy:                     'Display an error dialog   Dim rc%                    'Ask if should try again   rc% = MsgBox("Failed to copy from " & Src$ & " to " & Dest$ & " because: "&_          CHR$(10) & Error() & " at line " & Erl & CHR$(10) &_          "Try again?", (4 OR 32), "Error Copying")   If rc% = 6 Then    'Yes     Resume           'Try the command again   End If   If rc% = 7 Then    'No     Resume AllDone   'Go to the AllDone label   End If End Sub 
end example
 



OpenOffice.org Macros Explained
OpenOffice.org Macros Explained
ISBN: 1930919514
EAN: 2147483647
Year: 2004
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net