IN THE SPOTLIGHT: MDE to MDB Conversion Service
(also supports: ACCDE to ACCDB, ADE to ADP, etc)
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.
This feature requires v1.3+ of the Global Error Handler.
Let's say we have two procedures - namely Foo and Bar. Foo has local error handling yet Bar does not. Foo calls Bar and Bar generates an exception. Since there is no error handling in Bar, the error 'propagates' back to Foo where it is handled there. This is how error handling works in both VBA and VB6.
Public Sub Foo() On Error Goto ErrorRoutine Call Bar Exit Sub ErrorRoutine: MsgBox "An error has occurred in Foo" End Sub Public Sub Bar() Debug.Print 1 / 0 ' This will force an exception, but will be handled in Foo End Sub
In your global error handling procedure you can detect when an error will be propagated back to an earlier procedure in the call stack by examining the ErrEx.State value. In this case, ErrEx.State will equal the constant value OnErrorPropagate.
If when your global error handler exits, the ErrEx.State still equals OnErrorPropagate (i.e. you haven't changed the value) then the code flow will continue at the last procedure in the call stack that has error handling enabled (i.e. 'Foo' in this example).
In other words you don't need to do anything special in order to support error propagation as it complies with how VBA (and VB6) works normally - just be aware of it and how to use it.
When a propagating error occurs, you might find it useful to log the source of the error ('Bar' in the example) and also the routine that will ultimately handle the error ('Foo' in the example).
We already have details of 'Bar' as this is at the top of the call stack, so ErrEx.SourceProcedure will give us that.
To find details of the procedure that will ultimately handle the error, we need to find the first match in the call stack that has active error handling - and it's that simple. (Remember that the call stack is backwards - where 'Bar' is the first item, 'Foo' the second etc).
To do this, we use ErrEx.CallStack.HasActiveErrorHandler:
Public Sub MyGlobalErrorHandler() Select Case ErrEx.State Case OnErrorGoto0 '... Case OnErrorGotoLabel '... Case OnErrorPropagate With ErrEx.CallStack .FirstLevel Do If .HasActiveErrorHandler = True Then strErrorWillPropagateTo = .ProjectName & "." & .ModuleName & "." & .ProcedureName Exit Do End If Loop While .NextLevel End With '... End Select End Sub