no quiero que a las embarcaciones de controladores de errores especiales para cada estructura de bucle en mi código, así que tengo una manera de encontrar un problema bucles que utilicen mi gestor de errores estándar, de modo que pueda luego escribe un controlador de error especial para ellos.
Si se produce un error en un ciclo, normalmente quiero saber qué fue lo que causó el error en lugar de omitirlo. Para conocer estos errores, escribo mensajes de error en un archivo de registro como hacen muchas personas. Sin embargo, escribir en un archivo de registro es peligroso si se produce un error en un ciclo, ya que el error se puede desencadenar cada vez que se repite el ciclo y en mi caso 80 000 iteraciones no es infrecuente.Por lo tanto, he puesto un código en mi función de registro de errores que detecta errores idénticos y omite escribirlos en el registro de errores.
Mi controlador de error estándar que se utiliza en cada procedimiento tiene este aspecto. Registra el tipo de error, el procedimiento en el que se produjo el error y los parámetros del procedimiento recibido (FileType en este caso).
procerr:
Call NewErrorLog(Err.number, Err.Description, "GetOutputFileType", FileType)
Resume exitproc
Mi función de registro de errores que escribe en una tabla (estoy en ms-access) es la siguiente. Utiliza variables estáticas para retener los valores previos de los datos de error y compararlos con las versiones actuales. Se registra el primer error, luego el segundo error idéntico empuja a la aplicación al modo de depuración si soy el usuario o si en otro modo de usuario, abandona la aplicación.
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
Tenga en cuenta que un registrador de error tiene que ser la función más a prueba de balas en su aplicación ya que la aplicación no puede controlar correctamente errores en el registrador de error. Por esta razón, utilizo NZ() para asegurarme de que los nulos no puedan entrar sigilosamente. Tenga en cuenta que también agrego [loop] al segundo error idéntico, de modo que sé que primero busco los bucles en el procedimiento de error.
¿No hay 'objetos de lista' que no son tablas de consulta? Necesito la hoja para tener una tabla de consulta. –
@Justin, de ser así, agregue una prueba para 'ListObjects (1) .QueryTable Is Nothing'; su código tampoco tenía esta prueba. El punto principal de mi muestra es verificar si la colección ListObjects tiene algún elemento antes de desreferenciar el primer elemento. – Joe