我不想为代码中的每个循环结构编写特殊的错误处理程序,因此我需要一种方法来使用我的标准错误处理程序找到问题循环,以便我可以为它们编写特殊的错误处理程序。
如果在循环中发生错误,通常我希望知道导致错误的原因,而不仅仅是跳过它。为了了解这些错误,我像许多人一样将错误消息写入日志文件。但是,如果在循环中发生错误,则写入日志文件是危险的,因为错误可能会在循环迭代的每次触发,并且在我的情况下,80000次迭代并不罕见。因此,我已经将一些代码放入我的错误记录函数中,以检测相同的错误并跳过将它们写入错误日志。
我用于每个过程的标准错误处理程序如下所示。它记录错误类型、发生错误的过程以及过程接收的任何参数(在本例中为FileType)。
procerr:
Call NewErrorLog(Err.number, Err.Description, "GetOutputFileType", FileType)
Resume exitproc
我的错误日志功能会将内容写入表格(我在使用ms-access),如下所示。它使用静态变量来保留先前的错误数据并将其与当前版本进行比较。第一个错误被记录,然后第二个相同的错误会将应用程序推入调试模式,如果我是用户或在其他用户模式下,则退出应用程序。
Public Function NewErrorLog(ErrCode As Variant, ErrDesc As Variant, Optional Source As Variant = "", Optional ErrData As Variant = Null) As Boolean
On Error GoTo errLogError
'Records errors from application code
Dim dbs As Database
Dim rst As Recordset
Dim ErrorLogID As Long
Dim StackInfo As String
Dim MustQuit As Boolean
Dim i As Long
Static ErrCodeOld As Long
Static SourceOld As String
Static ErrDataOld As String
'Detects errors that occur in loops and records only the first two.
If Nz(ErrCode, 0) = ErrCodeOld And Nz(Source, "") = SourceOld And Nz(ErrData, "") = ErrDataOld Then
NewErrorLog = True
MsgBox "Error has occured in a loop: " & Nz(ErrCode, 0) & Space(1) & Nz(ErrDesc, "") & ": " & Nz(Source, "") & "[" & Nz(ErrData, "") & "]", vbExclamation, Appname
If Not gDeveloping Then 'Allow debugging
Stop
Exit Function
Else
ErrDesc = "[loop]" & Nz(ErrDesc, "") 'Flag this error as coming from a loop
MsgBox "Error has been logged, now Quiting", vbInformation, Appname
MustQuit = True 'will Quit after error has been logged
End If
Else
'Save current values to static variables
ErrCodeOld = Nz(ErrCode, 0)
SourceOld = Nz(Source, "")
ErrDataOld = Nz(ErrData, "")
End If
'From FMS tools pushstack/popstack - tells me the names of the calling procedures
For i = 1 To UBound(mCallStack)
If Len(mCallStack(i)) > 0 Then StackInfo = StackInfo & "\" & mCallStack(i)
Next
'Open error table
Set dbs = CurrentDb()
Set rst = dbs.OpenRecordset("tbl_ErrLog", dbOpenTable)
'Write the error to the error table
With rst
.AddNew
!ErrSource = Source
!ErrTime = Now()
!ErrCode = ErrCode
!ErrDesc = ErrDesc
!ErrData = ErrData
!StackTrace = StackInfo
.Update
.BookMark = .LastModified
ErrorLogID = !ErrLogID
End With
rst.Close: Set rst = Nothing
dbs.Close: Set dbs = Nothing
DoCmd.Hourglass False
DoCmd.Echo True
DoEvents
If MustQuit = True Then DoCmd.Quit
exitLogError:
Exit Function
errLogError:
MsgBox "An error occured whilst logging the details of another error " & vbNewLine & _
"Send details to Developer: " & Err.number & ", " & Err.Description, vbCritical, "Please e-mail this message to developer"
Resume exitLogError
End Function
注意,错误记录器必须是应用程序中最坚固的功能,因为应用程序无法在错误记录器中优雅地处理错误。因此,我使用NZ()来确保空值不能悄悄进入。请注意,我还将[loop]添加到第二个相同的错误中,以便我知道首先要查看错误过程中的循环。