Centralized Error Handling

See Also

When you add error-handling code to your applications, you'll quickly discover that you're handling the same errors over and over. With careful planning, you can reduce code size by writing a few procedures that your error-handling code can call to handle common error situations.

The following FileErrors function procedure shows a message appropriate to the error that occurred and, where possible, allows the user to choose a button to specify what action the program should take next. It then returns code to the procedure that called it. The value of the code indicates which action the program should take. Note that user-defined constants such as MnErrDeviceUnavailable must be defined somewhere (either globally, or at the module level of the module containing the procedure, or within the procedure itself). The constant vbExclamation is defined in the Visual Basic (VB) object library, and therefore does not need to be declared.

Function FileErrors () As Integer
   Dim intMsgType As Integer, strMsg As String
   Dim intResponse As Integer
   ' Return Value      Meaning
   ' 0                  Resume
   ' 1                  Resume Next
   ' 2                  Unrecoverable error
   ' 3                  Unrecognized error
   intMsgType = vbExclamation
   Select Case Err.Number
      Case MnErrDeviceUnavailable   ' Error 68.
         strMsg = "That device appears unavailable."
         intMsgType = vbExclamation + 4
      Case MnErrDiskNotReady      ' Error 71.
         strMsg = "Insert a disk in the drive "
         strMsg = strMsg & "and close the door."
         intMsgType = vbExclamation + 4
      Case MnErrDeviceIO         ' Error 57.
         strMsg = "Internal disk error."
         intMsgType = vbExclamation + 4
      Case MnErrDiskFull         ' Error 61.
         strMsg = "Disk is full. Continue?"
         intMsgType = vbExclamation + 3
      ' Error 64 & 52.
      Case ErrBadFileName, ErrBadFileNameOrNumber
         strMsg = "That filename is illegal."
         intMsgType = vbExclamation + 4
      Case ErrPathDoesNotExi      ' Error 76.
         strMsg = "That path doesn't exist."
         intMsgType = vbExclamation + 4
      Case ErrBadFileMode         ' Error 54.
         strMsg = "Can't open your file for that "
         strMsg = strMsg & "type of access."
         intMsgType = vbExclamation + 4
      Case ErrFileAlreadyOpen   ' Error 55.
         strMsg = "This file is already open."
         intMsgType = vbExclamation + 4
      Case ErrInputPastEndOfFile   ' Error 62.
         strMsg = "This file has a nonstandard "
         strMsg = strMsg & "end-of-file marker, "
         strMsg = strMsg & "or an attempt was made "
         strMsg = strMsg & "to read beyond "
         strMsg = strMsg & "the end-of-file marker."
         intMsgType = vbExclamation + 4
      Case Else
         FileErrors = 3
         Exit Function
   End Select
   intResponse = MsgBox (strMsg, intMsgType, _
   "Disk Error")
   Select Case intRresponse
      Case 1, 4      ' OK, Retry buttons.
         FileErrors = 0
      Case 5         ' Ignore button.
         FileErrors = 1
      Case 2, 3      ' Cancel, End buttons.
         FileErrors = 2
      Case Else
         FileErrors = 3
   End Select
End Function

This procedure handles common file and disk-related errors. If the error is not related to disk Input/Output, it returns the value 3. The procedure that calls this procedure should then either handle the error itself, regenerate the error with the Raise method, or call another procedure to handle it.

Note   As you write larger applications, you'll find that you are using the same constants in several procedures in various forms and modules. Making those constants public and declaring them in a single standard module may better organize your code and save you from typing the same declarations repeatedly.

You can simplify error handling by calling the FileErrors procedure wherever you have a procedure that reads or writes to disk. For example, you've probably used applications that warn you if you attempt to replace an existing disk file. Conversely, when you try to open a file that doesn't exist, many applications warn you that the file does not exist and ask if you want to create it. In both instances, errors can occur when the application passes the file name to the operating system.

The following checking routine uses the value returned by the FileErrors procedure to decide what action to take in the event of a disk-related error.

Function ConfirmFile (FName As String, _
Operation As Integer) As Integer
' Parameters:
' Fname: File to be checked for and confirmed.
' Operation: Code for sequential file access mode
' (Output, Input, and so on).
' Note that the procedure works for binary and random
' access because messages are conditioned on Operation
' being <> to certain sequential modes.
' Return values:
' 1      Confirms operation will not cause a problem.
' 0      User decided not to go through with operation.
   Const conSaveFile = 1, conLoadFile = 2
   Const conReplaceFile = 1, conReadFile = 2
   Const conAddToFile = 3, conRandomFile = 4
   Const conBinaryFile = 5
   Dim intConfirmation As Integer
   Dim intAction As Integer
   Dim intErrNum As Integer, varMsg As Variant
   
   On Error GoTo ConfirmFileError   ' Turn on the error
                                 ' trap.
   FName = Dir(FName)         ' See if the file exists.
   On Error GoTo 0            ' Turn error trap off.
   ' If user is saving text to a file that already
   ' exists...
   If FName <> "" And Operation = conReplaceFile Then
      varMsg = "The file " & FName &
      varMsg = varMsg & "already exists on " & vbCRLF
      varMsg = varMsg & "disk. Saving the text box " 
      varMsg = varMsg & & vbCRLF
      varMsg = varMsg & "contents to that file will "
      varMsg = varMsg & "destroy the file's current "
      varMsg = varMsg & "contents, " & vbCRLF _
      varMsg = varMsg & "replacing them with the "
      varMsg = varMsg & "text from the text box."
      varMsg = varMsg & vbCRLF & vbCRLF
      varMsg = varMsg & "Choose OK to replace file, "
      varMsg = varMsg & "Cancel to stop."
      intConfirmation = MsgBox(varMsg, 65, _
      "File Message")
   ' If user wants to load text from a file that
   ' doesn't exist.
   ElseIf FName = "" And Operation = conReadFile Then
      varMsg = "The file " & FName
      varMsg = varMsg & " doesn't exist." & vbCRLF
      varMsg = varMsg & "Would you like to create and       varMsg = varMsg & "then edit it?" & vbCRLF
      varMsg = varMsg & vbCRLF & "Choose OK to "
      varMsg = varMsg & "create file, Cancel to stop."
      intConfirmation = MsgBox(varMsg, 65, _
      "File Message")
   ' If FName doesn't exist, force procedure to return
   ' 0 by setting
   ' intConfirmation = 2.
   ElseIf FName = "" Then
      If Operation = conRandomFile Or _
      Operation = conBinaryFile Then
         intConfirmation = 2 
      End If
   ' If the file exists and operation isn't
   ' successful, 
   ' intConfirmation = 0 and procedure returns 1.
   End If
   ' If no box was displayed, intConfirmation = 0;
   ' if user chose OK, in either case,
   ' intConfirmation = 1 and ConfirmFile should 
   ' return 1 to confirm that the intended operation
   ' is OK. If intConfirmation > 1, ConfirmFile should
   ' return 0, because user doesn't want to go through
   ' with the operation...
   If intConfirmation > 1 Then 
      ConfirmFile = 0 
   Else 
      ConfirmFile = 1
      If Confirmation = 1 Then
         ' User wants to create file.
         If Operation = conLoadFile Then
            ' Assign conReplaceFile so caller will
            ' understand action that will be taken.
            Operation = conReplaceFile
         End If
      ' Return code confirming action to either
      ' replace existing file or create new one.
      End If
   End If
Exit Function
ConfirmFileError:
intAction = FileErrors
   Select Case intAction
      Case 0
         Resume
      Case 1
         Resume Next
      Case 2
         Exit Function
      Case Else
         intErrNum = Err.Number
         Err.Raise Number:=intErrNum
         Err.Clear
   End Select
End Function

The ConfirmFile procedure receives a specification for the file whose existence will be confirmed, plus information about which access mode will be used when an attempt is made to actually open the file. If a sequential file is to be saved (conReplaceFile), and a file is found that already has that name (and will therefore be overwritten), the user is prompted to confirm that overwriting the file is acceptable.

If a sequential file is to be opened (conReadFile) and the file is not found, the user is prompted to confirm that a new file should be created. If the file is being opened for random or binary access, its existence or nonexistence is either confirmed (return value 1) or refuted (return value 0). If an error occurs in the call to Dir, the FileErrors procedure is called to analyze the error and prompt the user for a reasonable course of action.