SimplyVBA and SimplyVB6
Global Error Handler v1.7.2
Tips: Converting existing code
On this page you'll find:
Overview
Here we will describe a method of implementing the Global Error Handler in a way that blends itself closely with existing code. As such, you will find examples side by side of the 'before' and 'after' stages.
Example Global Error Handling routine
Here is the global error handling routine to use to start with for these examples:
Public Sub MyGlobalErrorHandler_Release()
Select Case ErrEx.State
Case OnErrorGoto0
' ---------------------------------------------------------------
' Unhandled errors
' ---------------------------------------------------------------
LogErrorToTable
ErrEx.State = ErrEx.ShowErrorDialog
Case OnErrorGotoLabel
' ---------------------------------------------------------------
' Ignore locally handled errors
' ---------------------------------------------------------------
Case OnErrorPropagate
' ---------------------------------------------------------------
' Ignore locally handled errors
' (handled by a previous routine in the call stack)
' ---------------------------------------------------------------
Case OnErrorResumeNext
' ---------------------------------------------------------------
' Ignore errors when On Error Resume Next is set
' ---------------------------------------------------------------
Case CalledByLocalHandler
' ---------------------------------------------------------------
' ErrEx.CallGlobalErrorHandler was called
'
' This is a special case for when local error handling was in use
' but the local error handler has not dealt with the error and
' so has passed it on to the global error handler
' ---------------------------------------------------------------
LogErrorToTable
ErrEx.State = ErrEx.ShowErrorDialog
' ---------------------------------------------------------------
' NOTE:
'
' Since this global error handler routine is for 'release', not
' 'development', we don't really want to end abruptly here.
'
' So instead, we set ErrEx.Status = CalledByLocalHandler
' which ensures we resume after the CallGlobalErrorHandler
' line - where cleanup code can then be done
' ---------------------------------------------------------------
ErrEx.State = CalledByLocalHandler
End Select
End Sub
This routine is very typical and makes the system work similarly to the existing way VBE handles errors, albeit with many more features…
Example 1: No local error handling required
When you think about it logically, the majority of VB subroutines do not need to handle specific errors but instead just need to show a warning / error dialog when an error occurs (and perhaps log errors to a file or table).
This is the best scenario for us because we can now cut down the VB code considerably:
| Before (without global error handling) | | After (using global error handler) |
Private Sub btnMyButton_Click()
On Error Goto LocalErrorHandler
DoCmd.OpenForm "ABC"
Exit Sub
LocalErrorHandler:
MsgBox "Error occured in btnMyButton_Click: " & _
Err.Description & " (" & CStr(Err.Number) & ")"
LogErrorToTable Err.Number, Err.Description
End Sub
| | Private Sub btnMyButton_Click()
DoCmd.OpenForm "ABC"
End Sub
|
As this example shows, we no longer need to provide any local error handling when you're not needing to catch specific errors. The reason for this is that even though no local error handler has been set, our global error handling routine still gets called but with an ErrEx.State of OnErrorGoto0 which indicates no error handling has been set.
Furthermore, there's no need to pass over the name of the procedure since this information is all available from within your global error handling routine.
Benefits
- Smaller code
- Easier to read
- Easier to maintain
- All the added features of the Global Error Handler - such as reading the CallStack, automatic line numbering and live variable inspection in the procedure of error
Example 2: Catching expected errors in a local error handler
There will be times when you need to catch an expected error in your local procedure yet still show a warning / error dialog for other, unhandled errors.
With our Global Error Handler, this is very similar to how you would do this normally:
| Before (without global error handling) | | After (using global error handler) |
Public Function IsMDE() As Boolean
On Error GoTo LocalErrorHandler
Dim db As DAO.Database
Set db = CurrentDb()
If db.Properties("MDE") = "T" Then
IsMDE = True
End If
Set db = Nothing
Exit Function
LocalErrorHandler:
If Err.Number = 3270 Then
'Property Not Found
Exit Function
End If
'An unexpected error has occured
MsgBox "Error occured in IsMDE: " & _
Err.Description & " (" & CStr(Err.Number) & ")"
LogErrorToTable Err.Number, Err.Description
End Function | | Public Function IsMDE() As Boolean
On Error GoTo LocalErrorHandler
Dim db As DAO.Database
Set db = CurrentDb()
If db.Properties("MDE") = "T" Then
IsMDE = True
End If
Set db = Nothing
Exit Function
LocalErrorHandler:
If Err.Number = 3270 Then
'Property Not Found
Exit Function
End If
'An unexpected error has occured
ErrEx.CallGlobalErrorHandler
End Function |
This example shows that here we would change only two lines of code to get the same functionality. When our global error handler gets called at the 'ErrEx.CallGlobalErrorHandler' line, the ErrEx.State will be CalledByLocalHandler - which you can see a case statement for in our global error handler at the top of this page.
Again, there's no need to pass over the name of the procedure since this information is all available from within your global error handling routine.
Benefits
- Easier to read
- Easier to maintain
- All the added features of the Global Error Handler - such as reading the CallStack, automatic line numbering and live variable inspection in the procedure of error
Example 3: Catching expected errors and cleanup code
There are also times when you need to catch an expected error, show an error dialog for unhandled errors and also ensure that open objects (such as recordsets) are closed and de-referenced properly (even when unexpected errors occur).
With the Global Error Handler, this is again perfectly feasible and very similar to how you would do this normally:
| Before (without global error handling) | | After (using global error handler) |
Public Function IsMDE() As Boolean
On Error GoTo LocalErrorHandler
Dim db As DAO.Database
Set db = CurrentDb()
If db.Properties("MDE") = "T" Then
IsMDE = True
End If
Cleanup:
Set db = Nothing
Exit Function
LocalErrorHandler:
If Err.Number = 3270 Then
'Property Not Found
Exit Function
End If
'An unexpected error has occured
MsgBox "Error occured in IsMDE: " & _
Err.Description & " (" & CStr(Err.Number) & ")"
LogErrorToTable Err.Number, Err.Description
Resume Cleanup
End Function | | Public Function IsMDE() As Boolean
On Error GoTo LocalErrorHandler
Dim db As DAO.Database
Set db = CurrentDb()
If db.Properties("MDE") = "T" Then
IsMDE = True
End If
Cleanup:
Set db = Nothing
Exit Function
LocalErrorHandler:
If Err.Number = 3270 Then
'Property Not Found
Exit Function
End If
'An unexpected error has occured
ErrEx.CallGlobalErrorHandler
Resume Cleanup
End Function |
Again, not much difference here. In conclusion you can see just how little effort is needed to implement the global error handler into your applications.
Benefits
- Easier to read
- Easier to maintain
- All the added features of the Global Error Handler - such as reading the CallStack, automatic line numbering and live variable inspection in the procedure of error
Further reading / related pages: