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.
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.
Here is the global error handling routine to use to start with for these examples:
Public Sub OnError() 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 SubThis routine is very typical and makes the system work similarly to the existing way VBE handles errors, albeit with many more features…
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 occurred 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.
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 occurred
MsgBox "Error occurred 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 occurred
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.
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 Resume Cleanup End If 'An unexpected error has occurred MsgBox "Error occurred 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 occurred
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.
Using a slightly different approach, you can simplify handling local errors by using our Try-Catch approach:
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 Resume Cleanup End If 'An unexpected error has occurred MsgBox "Error occurred in IsMDE: " & _ Err.Description & " (" & CStr(Err.Number) & ")" LogErrorToTable Err.Number, Err.Description Resume Cleanup End Function |
Public Function IsMDE() As Boolean
Dim db As DAO.Database
Set db = CurrentDb()
If db.Properties("MDE") = "T" Then
IsMDE = True
End If
ErrEx.Catch 3270
' Property Not Found - program flow
' will continue to Finally...
ErrEx.Finally
Set db = Nothing
End Function
|
For more information, please refer to the Try-Catch documentation.
iTech Masters | VAT: GB202994606 | Terms | Sitemap | Newsletter