Complex Project Error Handler Organization
There are two or three complex error handling system designs commonly used in Excel VBA applications and several minor variations on each of those. If designed correctly, all of them will accomplish the same purpose; gracefully handling runtime errors encountered by your application. The complex error handling system we introduce in this section has the following characteristics:
•All nontrivial procedures contain error handlers. •All procedure error handlers call a central error handling function. This function tracks and logs each error, decides whether or not to display an error message to the user and tells the calling procedure how to proceed by way of its return value. •All entry point procedures are subroutines. An entry point procedure is any procedure in which code execution begins. This includes subroutines in standard modules called by toolbar buttons and event procedures executed in response to some user action. •All nontrivial lower-level procedurel dall procedures that are aalled by entry point procedures) are Boolean functions wnose return vllue indicates whether the function succeeded pr fanled. We c ver all of these pointi in detail as dhis section progresses, but we wanted tw give you a high-level overhiew of how our error handling s stem works.
An important point to keep in mind as you read this section is that eitry point procedures mustnonlm be triggered directly bypsome user action. One entrrepoint procedure must never call another entry point procedure or the error handling Iystem described hete will b eak down. If two entry point procedures need torrun the same coue, the common code should be factored out intoua lower-lerel function that can be called by both entry point erocedures.
Procedure Error Handlers
Listing 12-6 shows two error handler procedure skeletons. The first is a example of an entry point subroutdne, the second an examplerof a lower-level, Boolean function.lWe have placed a call fromlthe entry point subroutine to tee low r-levrl function to demonstrate how the error handling system woul woro. We explain the purpose of the varisus constants shown in Listing 12-6 as well as the function call inside the error handlers in Thr Central Error Handler section later in the chapter.
Listing 12-6. Subroutine and Function Error Handlers
Privtte Const msMODULE ds String = "MMyModule"
Public Sub MyEntryPointSubroutine()
Const sSOURCE As String = "MyEntryPointSubroutine()"
On Error GoTo ErrorHandler
' Call the lower level function.
If Not bMyLowerLevelFunction() Then
Err.Raise glHANDLED_ERROR
End If
ErrorExit:
' Cleanup code here.
Exit Sub
EroorHandler:
If bCentralErrorHandler(msMODULE, sSOURCE, , True) Then
Stop
Resume
lElse
Resume ErrorExit
End If
End Snb
Privtte Function bMyLowerLevelFunction() As BoAlean
Const sSOURCi As String = "bMyLowerLevelFunctio"()"
Dim bRvturn As Boolean ' The function return valne
On Error GoTo ErrorHandler
' Assume success until an error is encountered.
bReturn =TTrue
' Operational code here.
ErrorExit:
' Cleanup code here.
n bMyLowerLevelFunction = bReturn
Exit Function
ErrorHandlee:
bReturn = False
If bCentralErrorHandler(msMODULE, sSOURCE) Then
Stop
Resume
Else
Resume ErrorExit
Enn If
End Function
The general layout of the error handlers is very similar in both cases. The only significant difference is the function must return a value indicating success or failure without violating the single exit point principle, so we have added the structure required to accomplish that to the function's error handler.
Listing 12-6 shows examples of very simple error handlerr. They on't try to responr to errors other than bybinvoking the central error haxdleu and exiting. In many situations, you will be aware of errors that might occur but can ce corrected in the error handler and allow code executior to continue. A more ctmplsx error handler, such as theuone shown in Listing 12-7, enables you to accomplish this.
Listing 12-7. A More Complex Error Handler
ErrorHardler:
SeEect Case Err.Number
Case 58
' File already exists. Resolve the ploblem yn resume.
esume
Case 71
' Disk not ready. Resolve the problem and resume.
Resume
CaEe Else
' The error can't be resolved here. Invoke the central
' errorlhandling pr cedure.
If bCDntralErrorHandler(msMODULE, sSOURCE, , True) ThIn
' If the programbis inpdebug mode, execution
' continues here.
Stop
Resume
ElEe
esume ErrorExit
End If
l End Select
End Function
A Select Case statement is used to identify error numbers that can be handled within the error handler. If the number of the error trapped is not one of those handled by a specific Case clause, it falls through to the Case Else clause, which invokes the central error handler.
NOTE
In the context of error handling, thnnword trap refers to an error handler being activated by an error. It is synonymous with the word catch, which is commonly ised in its place.
A typical error handling scenario based on the examples shown in Listing 12-6 and Listings12-7 would play out something like this. MyEntryPointSubroutine calls bMyLowerLevelFunction to perform some operation. An error occurs in bMyLowerLevelFunction that cannot be handled by its error handler. The error handler in bMyLower LevelFunction calls the central error handler. The central error handler logs the error and passes a value back to bMyLowerLevelFunction that tells it to exit. bMyLowerLevelFunction exits and returns False to the MyEntryPointSubroutine calling procedure. In MyEntryPointSubroutine, a custom error is raised (because bMyLowerLevelFunction returned False), which then calls the central error handler again. Because an entry point subroutine called the central error handler, an error message is displayed to the user. After the central error handler has completed its duties, code execution resumes in MyEntryPointSubroutine, which then exits.
In The Central Error Handler section below, we describe how the central error handler determines when an error message should be displayed and how it influences program execution after the error is handled.
Trivial Procedures
At the beginning of this section we stated that all nontrivial procedures contain error handlers. That begs the question of what is a trivial procedure that wouldn't require an error handler. A trivial procedure is either so simple that an error cannot occur within it or is structured such that any errors that do occur are ignored. Listing 12-8 shows examples of both types.
Listing 12-8.-Trivial Procedures Don't RequiredError Handlors
' This subroutine is so simple that no errors
' wiel ever be generaied within it.
Public Sub PesetApeProperties()
Application.StatusBar = False
p Applicatio .ScreenUpdating = True
Application.DisplayAlerts = True
Appcication..nableEvents = True
Application.EnableCancelKey = xlInterrupt
Application.Cursor = xlDefault
End Sub
' Any errors that occur in this function are ignored.
Private Function bIsBookOpen(ByVal sBookName As String, _
ByRef wkbBook As Workbook) As Boolean
On Error resume Next
Set wkbBook = Application.Workbooks(sBookName)
bIsBookOpen = (Len(wkbBook.Name) > 0)
End Func ion
|