Alison Balteramp;#039;s Mastering Microsoft Office Access 1002003 [Electronic resources]

Alison Balter

نسخه متنی -صفحه : 544/ 280
نمايش فراداده

Building a Custom Error Handler Class

Implementing error handling within an application can be very tedious, especially if you attempt to place specific error-handling logic in each routine you write. Although implementing a generic error handler does not mandate the use of a class module, using a class module greatly facilitates the process of implementing error handling within your applications. Listing 16.29 illustrates this point.

Listing 16.29 An Example of an Access Subroutine
Sub AnySub2() 'Declare constant with the name of the routine Const SUBNAME As String = "AnySub" 'Invoke error handling On Error GoTo AnySub2_Err 'Beginning of any routine MsgBox "This is the rest of your code...." 'Oops! Something causes an error! Err.Raise 11 'Code after the error MsgBox "We are Past the Error!!" AnySub2_Exit: 'Generic exit point for routine Exit Sub AnySub2_Err: Dim intAction As Integer 'Instantiate the error handler class Set gobjErrorHandler = New ErrorHandler 'Execute the ErrorProcess method, 'passing the error information intAction = gobjErrorHandler.ErrorProcess(ModuleName, _ SUBNAME, Err.Number, Err.Description) 'Evaluate return value to determine what action to take Select Case intAction Case ERR_CONTINUE Resume Next Case ERR_RETRY Resume Case ERR_EXIT Resume AnySub2_Exit Case ERR_QUIT Quit End Select End Sub

When an error occurs, your code instantiates the ErrorHandler class. The Initialize event of the class executes, as shown in Listing 16.30.

Listing 16.30 The Initialize Event of the ErrorHandler Class
Private Sub Class_Initialize() 'Place username into private variable mstrUsername = CurrentUser 'Place current date and time into private variable mdatDateTime = Now End Sub

The Initialize event of the class sets the module-level variables mstrUserName and mdatDateTime equal to the CurrentUser and the current date and time, respectively. The Username and DateTime properties of the class use these variables.

The code then executes the ErrorProcess method of the ErrorHandler class, which logs the error and then takes appropriate action in response to the error. It appears in Listing 16.31.

Listing 16.31 The ErrorProcess Method of the ErrorHandler Class
Public Function ErrorProcess(strRoutine As String, _ strModule As String, _ lngErrorNumber As Long, _ strErrorMessage As String) As Integer 'Store error information into module-level variables mstrRoutine = strRoutine mstrModule = strModule mlngErrorNumber = lngErrorNumber mstrErrorMessage = strErrorMessage 'Log error Call LogError 'Locate the error number in tblErrors to 'determine how you should respond to the error Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.Open "Select Response from tblErrors Where ErrorNum = " & lngErrorNumber, _ CurrentProject.Connection, adOpenStatic 'If the error number that occurred is not found 'in tblErrors, display the error form and return 'ERR_QUIT to the problem routine If rst.EOF Then DoCmd.OpenForm "frmError2", WindowMode:=acDialog, _ OpenArgs:="ErrorHandler" ErrorProcess = ERR_QUIT 'If the error is in tblErrors, evaluate the contents of 'the Response field. Respond appropriately, displaying the appropriate 'form and returning the appropriate value to the offending routine Else Select Case rst!Response Case ERR_QUIT DoCmd.OpenForm "frmError2", WindowMode:=acDialog, _ OpenArgs:="Critical Error: Application will Terminate" ErrorProcess = ERR_QUIT Case ERR_RETRY ErrorProcess = ERR_RETRY Case ERR_EXIT DoCmd.OpenForm "frmError2", WindowMode:=acDialog, _ OpenArgs:="Severe Error: Processing Did Not Complete" ErrorProcess = ERR_EXIT Case ERR_CONTINUE ErrorProcess = ERR_CONTINUE End Select End If End Function

The routine first sets the ModuleName, Routine, ErrorMessage, and ErrorNumber variables within the class to the values of the parameters passed to the ErrorProcess method. The Property Get routines for the ModuleName, Routine, ErrorMessage, and ErrorNumber properties, which are responsible for manipulating error information, appear in Listing 16.32. Because we only want the properties to be set via the ErrorProcess method, no Property Let routines exist.

Listing 16.32 The Property Get Routines of the Class
Public Property Get ModuleName() As String ModuleName = mstrModule End Property Public Property Get Routine() As String Routine = mstrRoutine End Property Public Property Get ErrorMessage() As String ErrorMessage = mstrErrorMessage End Property Public Property Get ErrorNumber() As Integer ErrorNumber = mlngErrorNumber End Property Public Property Get UserName() As String UserName = mstrUsername End Property Public Property Get DateTime() As Date DateTime = mdatDateTime End Property

As you can see, the Property Get routines retrieve the values from their associated module-level variables.

Next, the function calls a routine that logs the error that occurred. This LogError routine is shown in Listing 16.33. The LogError routine uses ADO code to add a record to the tblErrorLog table. The record contains all the information about the error that occurred. Notice that the error information is retrieved from the module-level variables populated by the ErrorHandler class's ErrorProcess method.

Listing 16.33 The LogError Subroutine

[View full width]

Sub LogError() 'Declare a Connection object Dim cnn As ADODB.Connection Dim strSQL As String 'Point the Connection object at the connection 'associated with the current project Set cnn = CurrentProject.Connection 'Build a SQL statement that inserts error information 'into the tblErrorLog table strSQL = "INSERT INTO tblErrorLog ( ErrorDate, ErrorTime, UserName, ErrorNum, ErrorString, ModuleName, RoutineName) " strSQL = strSQL & "Select #" & Me.DateTime & "#, #" _ & Me.DateTime & "#, '" _ & Me.UserName & "', " _ & Me.ErrorNumber & ", '" _ & Me.ErrorMessage & "', '" _ & Me.ModuleName & "', '" _ & Me.Routine & "'" 'Execute the SQL statement cnn.Execute strSQL, , adExecuteNoRecords End Sub

After the error is logged, the number of the error that occurred is looked up in the tblErrors table. If it is not found in the tblErrors table, a form is displayed, containing all the critical information about the error that occurred. The value contained in the constant ERR_QUIT is returned from the ErrorHandler function. If the error number is found in the tblErrors table, the value contained in the Response field is evaluated. If it is the value contained in the constant ERR_QUIT, the frmError form is displayed, and the value in the constant ERR_QUIT is returned from the ErrorHandler method. If the Response field contains the value of the ERR_RETRY constant, that value is returned from the method, without the frmError form being displayed. If the Response field contains the value associated with the ERR_EXIT constant, the frmError form is displayed, and the ERR_EXIT value is returned from the ErrorHandler method. Finally, if the value in the Response field is the value associated with the ERR_CONTINUE constant, no error information is displayed, and the ERR_CONTINUE value is returned from the ErrorHandler method.

All the code contained in the ErrorHandler class is similar to that contained in the basErrorHandler module. The code has been modified so that it is implemented using properties and methods of a Class object.

The other code that is changed to use classes is the code behind the error form. Listing 16.34 shows the load event of the error form, modified to call methods of the appropriate classes.

Listing 16.34 The Form_Load Event of the Error Form
Private Sub Form_Load() Dim objSys As SystemInformation Set objSys = New SystemInformation 'Call routine to obtain system information Call objSys.GetSysInfo(Me) 'Call routine to obtain error information Call gobjErrorHandler.GetErrorInfo(Me) 'If FormCaption property contains a value, use the 'value as the caption for the form If Not IsNull(Me.OpenArgs) Then Me.lblAction.Caption = Me.OpenArgs End If End Sub

Notice that instead of calling the GetSysInfo function and the GetErrorInfo function, the load event executes the GetSysInfo method of the SystemInformation object and the GetErrorInfo method of the ErrorHandler object.

The GetSystemInfo function and associated declarations were moved to a SystemInformation class. No other changes were made to the code.

The GetErrorInfo function was moved to the ErrorHandler class and modified to retrieve properties of the class, as shown in Listing 16.35.

Listing 16.35 The GetErrorInfo Method of the ErrorHandler Class Retrieving Properties of the Class
Sub GetErrorInfo(frmAny As Form) 'Populate form controls with error information 'contained in the type variable frmAny.lblErrorNumber.Caption = Me.ErrorNumber frmAny.lblErrorString.Caption = Me.ErrorMessage frmAny.lblUserName.Caption = Me.UserName frmAny.lblDateTime.Caption = Format(Me.DateTime, "c") frmAny.lblModuleName.Caption = Me.ModuleName frmAny.lblRoutineName.Caption = Me.Routine End Sub

Notice that instead of using a type structure, the code references its own properties. The Private variables associated with these properties were set by the ErrorProcess method of the class.