IN THE SPOTLIGHT: MDE to MDB Conversion Service
(also supports: ACCDE to ACCDB, ADE to ADP, etc)
IN THE SPOTLIGHT: Access Database Repair Service
An in-depth repair service for corrupt Microsoft Access files
IN THE SPOTLIGHT: vbWatchdog
VBA error handling just got easier...
" vbWatchdog is off the chart. It solves a long standing problem of how to consolidate error handling into one global location and avoid repetitious code within applications. "
- Joe Anderson,
Microsoft Access MVP
Meet Shady, the vbWatchdog mascot watching over your VBA code →
(courtesy of Crystal Long, Microsoft Access MVP)
IN THE SPOTLIGHT: vbMAPI
An Outlook / MAPI code library for VBA, .NET and C# projects
Get emails out to your customers reliably, and without hassle, every single time.
Use vbMAPI alongside Microsoft Outlook to add professional emailing capabilities to your projects.
IN THE SPOTLIGHT: Code Protector
Standard compilation to MDE/ACCDE format is flawed and reversible.
To enable vbWatchdog, you simply call ErrEx.Enable(), passing the name of your global error handler subroutine as a string parameter:
Public Sub EnableWatchdog()
ErrEx.Enable "GlobalErrorTrap"
End Sub
Public Sub GlobalErrorTrap()
' ... this subroutine is now automatically called whenever
' an exception occurs in your code
End Sub
The most common use for the global error trap is to identify the location of the error (e.g. module/procedure name), logging the details and displaying an error dialog if necessary.
The GlobalErrorTrap subroutine must be defined in a standard VBA code module (except for classic VB6 users, who must read this instead).
Now let's see how we access some of the features available in vbWatchdog by discussing the basics of the ErrEx object.
Inside of your global error trap, you can determine the location of the error that occurred by reading the following ErrEx object properties:
.SourceProcedure | Returns the name of the procedure that caused the error |
.SourceModule | Returns the name of the module where the procedure resides |
.SourceProject | Returns the name of the VB project where the procedure resides |
.SourceLineNumber | Returns the debug line number of the error. See QuickStart: Automatic line numbering. |
.SourceLineCode | Returns the actual line of code that caused the error, in a string. Note that this property will return an empty string if the source code is not accessible, so use SourceLineNumber instead in those situations (e.g. for an Access MDE/ACCDE file). |
.SourceProjectFilename | Returns the VB project filename associated with the error. |
.SourceProjectConditionalCompilationArgs | Returns the compiler conditional arguments associated with the VB project. |
.SourceProjectIsCompiled [VBA only] | Returns a boolean value indicating the compilation state of the project associated with the error. |
.SourceProjectIsSaved [VBA only] | Returns a boolean value indicating whether all of the VBA modules in the VBA project are saved (not being edited). |
.SourceVBEProject [VBA only] | Returns the VBE object (from the Extensibility Library) associated with the error. |
The ErrEx.State property is arguably the most important property, and is used inside of your global error trap. It defines what will happen next after your error handler has finished executing.
Initially, when your error handler is called, the ErrEx.State property indicates what state the local error handling was in before the error occurred. If you wish to change how an error is to be handled from within your global error handler, then you can do so by changing the ErrEx.State value.
ErrEx.State can be one of five values when your global error handler is called:
OnErrorGoto0 | indicates no specific error handling has been set (or 'On Error Goto 0') |
OnErrorResumeNext | indicates ‘On Error Resume Next’ was set |
OnErrorGotoLabel | indicates ‘On Error Goto X’ was set |
OnErrorPropagate | indicates ‘On Error Goto X’ was set in a previous procedure in the stack (which will subsequently catch this error) |
CalledByLocalHandler | Special case, see A typical implementation of a global error handler |
vbWatchdog gives you the power to change the ErrEx.State value to any of the following values, which gives you the possibility of truly 'handling' an error at a global level, if you wish or need to do so. Once your global error trap routine has returned, vbWatchdog checks the ErrEx.State value that you have set, and takes the appropriate action:
OnErrorGoto0 | The vbWatchdog error dialog will be invoked. However, it is advised to use the explicit ErrEx.ShowErrorDialog method instead. |
OnErrorResumeNext | Execution will resume at the next line of code below the line of error. |
OnErrorRetry | Execution will resume at the line of error, causing the line of error to be re-executed. This is the equivalent of using 'Resume' in a local error handler in order to try the repeat the offending line to try again. This is useful for connection time-out issues etc. Warning: Use this state with caution to prevent a loop forming for permanent errors. |
OnErrorGotoLabel | Execution will resume at the label that was declared in the local procedure. |
OnErrorPropagate | Execution will resume at the label that was declared in a local procedure further up the call stack - see Error Propagation. This state can only be set if there is a previous call in the callstack that has active local error handling (i.e. OnErrorPropagate would be the ErrEx.State value on entry to your global handler). |
OnErrorDebug | The VBE debugger will break at the line of code that caused the error. This state is only valid when source code is available. This has the same effect as the ‘Debug’ button on the standard VBE error dialog. This state is not available for compiled Access MDE/ACCDE applications - use the ErrEx.IsDebugable property to determine if the debug option is available at runtime. |
OnErrorEnd | The code will end abruptly. Any code that was due to execute immediately after the line that caused the error will not execute. This acts the same as the ‘End’ button on the standard error dialog. For Access MDE/ACCDE applications, this doesn't reset global variables (same behaviour as old VBE). |
OnErrorUnwind [v3+] | The callstack will be unwound in a controlled manner. Global variables will not lose their values, and any ErrEx.Finally blocks that are defined in the callstack will be executed. The error itself is not propagated, which can be particularly useful for preventing the Access Runtime from shutting down on unhandled VBA errors. |
OnErrorUnwindNoFinally [v3+] | As per OnErrorUnwind, but any ErrEx.Finally blocks will not be executed. |
OnErrorExitProcedure | This is the equivalent of using 'Exit Sub' or 'Exit Function' in a local error handler. This can be useful if you consistently use a Boolean return value to indicate success/failure in every function inside your project, as you can then use this state to pass the default return value back to the caller on error. |
CalledByLocalHandler | Special case, see A typical implementation of a global error handler |
One of the great features of the vbWatchdog is the customizable error dialog. This can be invoked by calling the ErrEx.ShowErrorDialog method from within your global error handler. ErrEx.ShowErrorDialog also conveniently returns a value that can be assigned directly to the ErrEx.State property (OnErrorEnd, OnErrorResumeNext, etc)
Public Sub GlobalErrorTrap() ErrEx.State = ErrEx.ShowErrorDialog() End Sub
For more details on customizing the error dialog, see QuickStart: Customizing the Error Dialog.
Typically, your global error handler will have a simple select-case statement that determines what the current state of the local error handling is, so that we can decide what to do next.
For example, when you set "On Error Goto XYZ" in your general code and an exception occurs, your global error handler will be invoked with an ErrEx.State value of OnErrorGotoLabel. In this case, you probably just want to pass this error on to the defined local error handler, and to do this you simply ensure that the ErrEx.State value isn't altered inside of your global error handler, and vbWatchdog will then pass the error on to your local error handler.
Additionally, if you later decide from inside your local error handler that you actually want to pass the error back to the global error handler again (for example, to display the error dialog), then you can call ErrEx.CallGlobalErrorHandler, which re-calls your global error handler with a special ErrEx.State value of CalledByLocalHandler. This gives you the opportunity to do some specific processing at the local level when an error occurs, whilst still being able to use the features of the global error handler.
Public Sub GlobalErrorTrap() Select Case ErrEx.State Case OnErrorGoto0, CalledByLocalHandler LogErrorToTable ' See Sample.MDB for LogErrorToTable (in module ModOnError), or LogErrorToFile ErrEx.State = ErrEx.ShowErrorDialog Case OnErrorGotoLabel, OnErrorPropagate, OnErrorResumeNext ' Do nothing... perhaps log the error if you wish. End Select End Sub Public Sub Example() On Error Goto MyLocalErrorHandler Debug.Print 1/0 ' Raise an error Exit Sub MyLocalErrorHandler: If Err.Number = 11 Then ' Division by zero error Resume Next Else ErrEx.CallGlobalErrorHandler ' Call the global error handler End If End Sub
In this example, the local error handler is handling local errors (division by zero in this example) and also passing any unhandled errors back on to the global error handler. Tip: To obtain a thorough understanding of this approach, the best advice is to copy the above example code into a VBA application, set a break point on it and step through the code line by line.
For taking this a step further and ensuring that all open objects (e.g. recordsets) are closed when an error occurs, see Demo 2 of the Sample.mdb.
Tip: An alternative approach to handling errors locally is to use the Try-Catch feature of vbWatchdog.
vbWatchdog provides two ways to read the callstack.
The first is from within your global error handling subroutine, where you can read the ErrEx.CallStack object properties to iterate through the details of the callstack relating to the error being dealt with.
The second method is from anywhere in your application you can read the ErrEx.LiveCallstack object properties to iterate through the details of the current callstack. The difference, for example, would be that using the ErrEx.LiveCallstack from inside global error handler would include the global error handler at the top of the callstack, whereas the ErrEx.Callstack object has the procedure of error at the top of the call stack.
For more details, please see Reading the callstack
.ShowHelp | This method simply opens the help file associated with the error (as given by ErrEx.HelpFile and ErrEx.HelpContext). |
.UserData | Read/Write variant property. Use this Variant property as storage if you want to pass an argument to your global error handler from your local procedure code. This property is automatically cleared after your global error handler next completes. |
.IsDebugable | This boolean property should be used when creating your own error dialogs to enable/disable the 'debug' button Use it to determine if you are able to break into the source code at runtime. For example, in MDE compiled Access applications, and VB6 compiled applications, this property will be False. Similarly if the error occurred in the immediate window then this property will be False but for most other times the property value will be True. |
.Version | This string property returns the vbWatchdog version information in the format "X.X.X". |
.VBEVersion | This string property returns the DLL version information of the VB engine in the format "X.X.X.X" |
.VariablesInspectorEnabled | Boolean property - default value is True. This property determines whether or not the VariablesInspector is active. Due to the nature of the VariablesInspector feature, it adds extra workload which gets performed when the VariablesInspector object is initially accessed when an error occurs. Typically the overheads incurred are so small that they are not worth worrying about - but in extreme cases (e.g. if you have thousands of variables in procedures) then you may wish to turn off the feature entirely here. |
.TypeInfoInspectorEnabled [v3+] | Boolean property - default value is True. When True, the vbWatchdog VariablesInspector further inspects generic Object and Variant data types to determine the real underlying object type (which is then provided in variables dumps and the TypeDesc property of the variables inspector). Also, this option allows vbWatchdog to determine array boundaries and outputs the extra information in the ValueDesc property… e.g. {ARRAY}(1 to 6) rather than just {ARRAY}. |
.LoadedDLLs [v3+] | String read-only property. Provides a dump of the names, paths and version numbers of all DLLs currently loaded by the running application process |
.ProjectFilterList | Read/Write String property vbWatchdog includes a filter that can be used to ignore errors from certain VBA projects. Without a filter, the Wizards used by Microsoft Access also use VBA, and as such, errors (whether handled or not) would ordinarily pass through your global error handler. The filter list is a string list of VBA project names, each separated by a semi-colon and the list is primarily used to prevent errors from the Access wizards from passing through to your global error handler. |
iTech Masters | VAT: GB202994606 | Terms | Sitemap | Newsletter