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.
vbWatchdog now supports a basic form of Try-Catch exception handling that can be used to simplify using a global error trap alongside local error handlers.
This is an example of a basic procedure when using the new Try-Catch concept:
Public Sub SimulateAnError() Debug.Print 1 / 0 ' Simulate division by zero error (error 11) Debug.Print "A" / 1 ' Simulate type mismatch error (error 13) Err.Raise &H123, , "This should be caught by the catch &H123 block..." Err.Raise &H456, , "This should be caught in the catch-all block..." ' Program flow now transfers to Finally... ErrEx.Catch 11, 13 ' you can set up a constant/enumeration if you prefer MsgBox "Error: either division by zero, or type mismatch!" Resume Next ErrEx.Catch &H123 ' you can set up a constant/enumeration if you prefer MsgBox "Error: caught error 291 (&H123)!" Resume Next ErrEx.CatchAll MsgBox "Error (catch-all):" & vbCrLf & vbCrLf & Err.Description Resume Next ErrEx.Finally MsgBox "Finally" Debug.Print 1 / 0 ' Errors here automatically ignored due to implicit OnErrorResumeNext End SubHere you can see several "blocks" of code:
When using this concept of error handling, you may wish to adjust your global error trap to take account of some new values of ErrEx.State:
OnErrorCatch |
This state indicates that the error that has been raised is due to be passed on to an ErrEx.Catch block that is defined
in the procedure of error.
When your global error trap exits, vbWatchdog checks that the ErrEx.State value hasn't been altered. If it hasn't, then vbWatchdog will move program execution to the ErrEx.Catch block so that the error can be handled locally. ErrEx.Number indicates which ErrEx.Catch block will ultimately catch the error. |
OnErrorCatchAll |
This state indicates that the error that has been raised is due to be passed on to an ErrEx.CatchAll block that is defined
in the procedure of error.
When your global error trap exits, vbWatchdog checks that the ErrEx.State value hasn't been altered. If it hasn't, then vbWatchdog will move program execution to the ErrEx.CatchAll block so that the error can be handled locally. |
OnErrorPropagateCatch |
This state indicates that the error that has been raised is due to be passed on to an ErrEx.Catch block that is defined
in a procedure deeper in the callstack (i.e. the top procedure doesn't have an ErrEx.Catch or CatchAll block to handle this error,
but a procedure earlier in the callstack does).
When your global error trap exits, vbWatchdog checks that the ErrEx.State value hasn't been altered. If it hasn't, then vbWatchdog will unwind the callstack and move program execution to the ErrEx.Catch block so that the error can be handled locally. ErrEx.Number indicates which ErrEx.Catch block will ultimately catch the error. |
OnErrorPropagateCatchAll |
This state indicates that the error that has been raised is due to be passed on to an ErrEx.CatchAll block that is defined
in a procedure deeper in the callstack (i.e. the top procedure doesn't have an ErrEx.Catch or CatchAll block to handle this error,
but a procedure earlier in the callstack does).
When your global error trap exits, vbWatchdog checks that the ErrEx.State value hasn't been altered. If it hasn't, then vbWatchdog unwind the callstack and move program execution to the ErrEx.CatchAll block so that the error can be handled locally. |
OnErrorInsideCatch |
This state indicates that the code in a local ErrEx.Catch block has itself caused an exception.
In standard VBA and VB6 error handling, errors that occur inside of a local error handler are treated as if no local error handling has been set (usually OnErrorGoto0, but can also be OnErrorPropagate). vbWatchdog emulates this standard error handling behaviour as long as you don't alter the ErrEx.State value during the execution of your global error handler trap. |
OnErrorInsideCatchAll | Same as OnErrorInsideCatch state, but for the case when code within a ErrEx.CatchAll block causes an error. |
OnErrorInsideFinally |
This state occurs if an exception is raised from within an ErrEx.Finally code block.
If you don't alter this value during the execution of your global error trap, then OnErrorResumeNext is implied so that errors that occur in the ErrEx.Finally block are effectively ignored. |
The main benefit of our try-catch approach is that when your global error handler catches an error you know immediately whether an error is specifically being handled locally (e.g. div-by-zero in the example). We know this since we can check if ErrEx.State in the global error trap equals OnErrorCatch or OnErrorPropagateCatch.
With a normal local error handler (such as on error goto xyz, which is similar to a CatchAll in the example), from within the global error handler you don’t know whether the local handler is actually designed to handle the specific error in question or not. If it’s not, then your local handler ends up calling ErrEx.CallGlobalErrorHandler again so that the global error handler can log the error and show the error dialog.
The try-catch approach allows you to simplify and clean up that local error handling code. With this approach, more often than not you won’t need a catch-all, but instead use a specific catch for a particular error number, and then the global error handler will treat all other errors as unhandled (keeping the error handling as tight as possible).
The new ErrEx.Rethrow method can be called inside an ErrEx.Catch or ErrEx.CatchAll block to pass the error down the callstack. Ordinarily, errors that occur inside a catch block won't propagate as they have the special ErrEx.State values of OnErrorInsideCatch, or equivalent.
The Rethrow method has optional arguments to override the error number, source and description texts. If they are omitted, then ErrEx.Rethrow will use the error number and description of the last error. Please note that the 'last error' may or may not be the error being handled by your ErrEx.Catch block if you don't call ErrEx.Rethrow immediately after the catch block!
To see a practical example, check out the Tips converting existing code (Example 4).
iTech Masters | VAT: GB202994606 | Terms | Sitemap | Newsletter