Adit Cookbook Pages

Home
Cookbook
A Question of Sorts
Bits & Bobs
Error Event Handling
SQL for Access
Grid Copy
Temporary Files
Delete or Kill
Credit Card
Virtual Arrays
Binary Chop
Numbers
VB to HTML
Viewport
Printing Grids

Error Event Handling

You have to work quite hard to trap and control unexpected errors using Visual Basic version 6. You have to protect almost every routine with an “On Error GoTo” statement and insert an appropriate error handling routine into it.

It makes sense to have a standard piece of code you can just paste into each routine to cover most eventualities - you can always add any special code required by a given situation. Personally, I never use the error handling routine to trap errors such as “Divide by Zero” - I check the value in code. I leave my error routines as a last resort and more particularly for dealing with routine database locks.

So let us start with a few public constants and variables that can be used by the error routines.

Public Const RetryLimit = 4
Public Const TimeLimit = 15
Public LockTime As Variant
Public TryAgain As Long
Public Msg As String, title As String
Public errorResponse As Long
 

You might want to play with the RetryLimit and TimeLimit values when tuning a systems responses to database locks. Their purpose is to allow the error routine to ignore short term locks in your database while limiting the total waiting time in the event that such locks are not resolved. The problem is that the Jet database engine (and others based upon it) also react to the number of users being supported by a given database - slowing it’s response to locks as the database is loaded. As we are reasonably happy with an Access database supporting up to 50 simultanious users this can be a problem on occasion.

If you are writing a class then you may want to signal errors found to the client program - so you should add the following to your class declarations.

Public Const MyE2999 = 2999
Private ClassErrorCode As Long
Private ClassErrorSource As String
Private ClassErrorMessage As String
 

So here is the main error recovery routine for subs and functions that include database access.

   Select Case Err
       'Case vbObjectError + MyE2999
           'Abort selected in a function called from this sub or function
           'Exit Sub
       Case 3006, 3007, 3008, 3009, 3261, 3050
           If IsNull(LockTime) Then
               LockTime = Time
           End If
           TryAgain = TryAgain + 1
           If TryAgain > RetryLimit Or DateDiff("s", LockTime, Time) > TimeLimit Then
               title = "Database Lock"
               Msg = "A database or database page is currently locked."
               Msg = Msg & vbLf & "The details of the lock are shown below"
               Msg = Msg & vbLf & "Error Code = " & CStr(Err) & vbLf & Error$
               Msg = Msg & VBLF & " in Sub:"
               Screen.MousePointer = vbDefault
               errorResponse = MsgBox(Msg, vbExclamation + vbAbortRetryIgnore, title)
               Select Case errorResponse
                   Case vbAbort
                   Case vbRetry
                       Resume
                   Case vbIgnore
                       Resume Next
               End Select
               ResetLimits
           Else
               If Err = 3050 Then
                   DoEvents
               End If
               Resume
           End If
       Case Else
           Screen.MousePointer = vbDefault
           errorResponse = MsgBox("An unexpected error has occured." & vbLf & "Please note the details." & vbLf & Error(Err) & vbLf & "in Sub:", vbExclamation + vbAbortRetryIgnore, "Unexpected Error")
           Select Case errorResponse
               Case vbAbort
               Case vbRetry
                   Resume
               Case vbIgnore
                   Resume Next
           End Select
   End Select
   Screen.MousePointer = vbDefault
   'ClassErrorCode = MyE2999
   'ClassErrorMessage = Error$
   'Err.Raise Number:=ClassErrorCode + vbObjectError, Source:=ClassErrorSource, Description:=ClassErrorMessage
   Exit Sub
 

You can copy and paste this routine into your subroutines and functions and then just modify the two lines that identify the routine. If you are pasting it into a function then you may need to change any “Exit Sub” lines to “Exit Function”. If the routine is being copied into a routine in a class module then un-comment the three penultimate lines to let the calling routine know about unresolved errors. If you are pasting into a routine that calls code in a class then un-comment the line that starts “Case VBObjectError” and it’s associated “Exit Sub” as the user will already know about the problem and has elected to terminate the current activity.

On occasion you may want to re-set the time and lock counting variables so make a call to this routine which you should locate somewhere suitable.

Public Sub ResetLimits()
  
   LockTime = Null
   TryAgain = 0
  
End Sub
 

If there is no database activity in your routine then the whole thing can be simplified - I keep a copy of both versions available ready to paste into my code as required.

   'Error Recovery - no Database
   Select Case Err
       Case vbObjectError + MyE2999
           'Abort selected in a function called from this sub or function
           Exit Sub
       Case Else
           Screen.MousePointer = vbDefault
           errorResponse = MsgBox("An unexpected error has occured." & vbLf & "Please note details." & vbLf & Error(Err) & vbLf & "in Sub:", vbExclamation + vbAbortRetryIgnore, "Unexpected Error")
           Select Case errorResponse
               Case vbAbort
               Case vbRetry
                   Resume
               Case vbIgnore
                   Resume Next
           End Select
   End Select
   Screen.MousePointer = vbDefault
   'ClassErrorCode = MyE2999
   'ClassErrorMessage = Error$
   'Err.Raise Number:=ClassErrorCode + vbObjectError, Source:=ClassErrorSource, Description:=ClassErrorMessage
   Exit Sub
 

Google
 
Web www.adit.co.uk
www.aditsite.co.uk