Vba 自动生成问题处理
这与其说是一个真正的问题,不如说是一个观察:MS Access(以及通常的VBA)非常缺少一个可以自动生成错误处理代码的工具,并且在发生错误时可以显示行号。你找到解决办法了吗?这是怎么一回事?我刚刚意识到,自从几年前我找到了这个基本问题的正确答案以来,我节省了数百个小时,我想看看你在这个非常重要的问题上有什么想法和解决方案 好吧,有两种工具可以满足您的要求并让您想起 基本上,它们包括添加一个:Vba 自动生成问题处理,vba,ms-access,error-handling,Vba,Ms Access,Error Handling,这与其说是一个真正的问题,不如说是一个观察:MS Access(以及通常的VBA)非常缺少一个可以自动生成错误处理代码的工具,并且在发生错误时可以显示行号。你找到解决办法了吗?这是怎么一回事?我刚刚意识到,自从几年前我找到了这个基本问题的正确答案以来,我节省了数百个小时,我想看看你在这个非常重要的问题上有什么想法和解决方案 好吧,有两种工具可以满足您的要求并让您想起 基本上,它们包括添加一个: On Error GoTo ErrorHandler 到每个过程的顶部 最后,他们提出: Error
On Error GoTo ErrorHandler
到每个过程的顶部
最后,他们提出:
ErrorHandler:
Call MyErrorhandler Err.Number, Err.Description, Err.LineNumber
标签中通常包含对全局错误处理程序的调用,您可以在其中显示和记录自定义错误消息。我的解决方案如下:
然后,通过单击MZ工具菜单中的相应按钮,可以将此标准错误代码自动添加到所有程序和功能中。您会注意到,这里我们指的是VBA标准库中的一个隐藏且未记录的函数“Erl”,它代表“error line”。你说对了!如果您要求MZ工具自动为代码行编号,“Erl”将为您提供发生错误的代码行编号。您将在即时窗口中完整描述错误,例如:
#91, Object variable or With block variable not set, l# 30, addNewField, Utilities
当然,一旦您意识到系统的重要性,您可以考虑一个更复杂的错误处理程序,它不仅会在调试窗口中显示数据,而且还会:
您可以像以前一样滚动自己的工具。VBA实际上可以通过访问自己的IDE。我已经编写了一些类模块,使自己的工作更容易。可以在上找到它们
我使用它插入
On Error GoTo ErrHandler
语句以及与错误处理模式相关的适当标签和常量。我还使用它将常量与实际过程名称同步(如果函数名称发生变化)。没有必要购买DJ提到的工具。以下是我的免费代码:
Public Sub InsertErrHandling(modName As String)
Dim Component As Object
Dim Name As String
Dim Kind As Long
Dim FirstLine As Long
Dim ProcLinesCount As Long
Dim Declaration As String
Dim ProcedureType As String
Dim Index As Long, i As Long
Dim LastLine As Long
Dim StartLines As Collection, LastLines As Collection, ProcNames As Collection, ProcedureTypes As Collection
Dim gotoErr As Boolean
Kind = 0
Set StartLines = New Collection
Set LastLines = New Collection
Set ProcNames = New Collection
Set ProcedureTypes = New Collection
Set Component = Application.VBE.ActiveVBProject.VBComponents(modName)
With Component.CodeModule
' Remove empty lines on the end of the code
For i = .CountOfLines To 1 Step -1
If Component.CodeModule.Lines(i, 1) = "" Then
Component.CodeModule.DeleteLines i, 1
Else
Exit For
End If
Next i
Index = .CountOfDeclarationLines + 1
Do While Index < .CountOfLines
gotoErr = False
Name = .ProcOfLine(Index, Kind)
FirstLine = .ProcBodyLine(Name, Kind)
ProcLinesCount = .ProcCountLines(Name, Kind)
Declaration = Trim(.Lines(FirstLine, 1))
LastLine = FirstLine + ProcLinesCount - 2
If InStr(1, Declaration, "Function ", vbBinaryCompare) > 0 Then
ProcedureType = "Function"
Else
ProcedureType = "Sub"
End If
Debug.Print Component.Name & "." & Name, "First: " & FirstLine, "Lines:" & ProcLinesCount, "Last: " & LastLine, Declaration
Debug.Print "Declaration: " & Component.CodeModule.Lines(FirstLine, 1), FirstLine
Debug.Print "Closing Proc: " & Component.CodeModule.Lines(LastLine, 1), LastLine
' do not insert error handling if there is one already:
For i = FirstLine To LastLine Step 1
If Component.CodeModule.Lines(i, 1) Like "*On Error*" Then
gotoErr = True
Exit For
End If
Next i
If Not gotoErr Then
StartLines.Add FirstLine
LastLines.Add LastLine
ProcNames.Add Name
ProcedureTypes.Add ProcedureType
End If
Index = FirstLine + ProcLinesCount + 1
Loop
For i = LastLines.Count To 1 Step -1
If Not (Component.CodeModule.Lines(StartLines.Item(i) + 1, 1) Like "*On Error GoTo *") Then
Component.CodeModule.InsertLines LastLines.Item(i), "ExitProc_:"
Component.CodeModule.InsertLines LastLines.Item(i) + 1, " Exit " & ProcedureTypes.Item(i)
Component.CodeModule.InsertLines LastLines.Item(i) + 2, "ErrHandler_:"
Component.CodeModule.InsertLines LastLines.Item(i) + 3, " Call LogError(Err, Me.Name, """ & ProcNames.Item(i) & """)"
Component.CodeModule.InsertLines LastLines.Item(i) + 4, " Resume ExitProc_"
Component.CodeModule.InsertLines LastLines.Item(i) + 5, " Resume ' use for debugging"
Component.CodeModule.InsertLines StartLines.Item(i) + 1, " On Error GoTo ErrHandler_"
End If
Next i
End With
End Sub
它将从以下内容更改您在Form1中的ode:
Private Function CloseIt()
DoCmd.Close acForm, Me.Name
End Function
为此:
Private Function CloseIt()
On Error GoTo ErrHandler_
DoCmd.Close acForm, Me.Name
ExitProc_:
Exit Function
ErrHandler_:
Call LogError(Err, Me.Name, "CloseIt")
Resume ExitProc_
Resume ' use for debugging
End Function
现在在模块中创建一个子模块,该子模块将显示错误对话框,您可以在其中将错误添加到文本文件或数据库:
Public Sub LogError(ByVal objError As ErrObject, moduleName As String, Optional procName As String = "")
On Error GoTo ErrHandler_
Dim sql As String
MsgBox "Error " & Err.Number & " Module " & moduleName & Switch(procName <> "", " in " & procName) & vbCrLf & " (" & Err.Description & ") ", vbCritical
Exit_:
Exit Sub
ErrHandler_:
MsgBox "Error in LogError procedure " & Err.Number & ", " & Err.Description
Resume Exit_
Resume ' use for debugging
End Sub
Public子日志错误(ByVal objError作为ErrObject,moduleName作为String,可选procName作为String=”“)
关于错误转到错误处理程序_
将sql设置为字符串
MsgBox“Error”和errr.Number&“Module”和moduleName&Switch(procName中的“,”)&vbCrLf&(“&Err.Description&”),vbCritical
退出:
出口接头
错误处理程序:
MsgBox“日志错误过程中的错误”&错误编号&“,”错误描述
恢复退出_
“恢复”用于调试
端接头
如果进程中已经有“On error”语句,则此代码不会进入错误处理。Good post,但我批评错误处理程序和退出例程没有统一名称的做法,例如errHandler和exitRoutine。由于标签范围的原因,没有理由将其特定于特定子项。这样可以更轻松地剪切和粘贴helluv。您是对的:无需为错误例程指定特定名称。但这并不重要,因为您不会从一个过程复制/粘贴到另一个过程,而是使用“插入错误代码”按钮,该按钮根据预定义的格式生成所需的行。错误时转到0是不必要的行,因为您将在下一行退出该过程。On Error Goto ErrorHandler语句在过程之外不适用这有点误导,因为Err.LineNumber不存在。。因此,虽然通用错误处理的良好实践,但它并没有回答关于行编号的原始问题的关键。如果您需要这样做,那么如果您必须有行号,那么涉及Erl的答案会更好。您不希望在代码中使用行号。读这篇:注意到了,同意了。我不想要行号。我的开发代码中没有任何行号。然后,当涉及到我的应用程序的用户版本时,我希望能够记录用户生成的错误,我正在添加它们(以自动方式),使错误跟踪变得更容易:(1)至少我可以检查来自特定模块的错误是否确实相同;(2)调试代码更快。当然,我没有任何超过65000行的程序!
Private Function CloseIt()
DoCmd.Close acForm, Me.Name
End Function
Private Function CloseIt()
On Error GoTo ErrHandler_
DoCmd.Close acForm, Me.Name
ExitProc_:
Exit Function
ErrHandler_:
Call LogError(Err, Me.Name, "CloseIt")
Resume ExitProc_
Resume ' use for debugging
End Function
Public Sub LogError(ByVal objError As ErrObject, moduleName As String, Optional procName As String = "")
On Error GoTo ErrHandler_
Dim sql As String
MsgBox "Error " & Err.Number & " Module " & moduleName & Switch(procName <> "", " in " & procName) & vbCrLf & " (" & Err.Description & ") ", vbCritical
Exit_:
Exit Sub
ErrHandler_:
MsgBox "Error in LogError procedure " & Err.Number & ", " & Err.Description
Resume Exit_
Resume ' use for debugging
End Sub