[英]MS-Access, VBA and error handling
這更像是一個觀察而不是一個真實的問題:MS-Access(以及一般的VBA)極度缺少一個可以自動生成錯誤處理代碼的工具,以及發生錯誤時可以顯示行號的工具。 你找到了解決方案嗎? 它是什么? 我剛剛意識到,自從幾年前我找到了解決這個基本問題的正確答案以來,我有多少個小時,我希望看到你在這個非常重要的問題上有什么想法和解決方案。
如何使用“Erl”,它會顯示錯誤之前的最后一個標簽(例如10,20或30)?
Private Sub mySUB()
On Error GoTo Err_mySUB
10:
Dim stDocName As String
Dim stLinkCriteria As String
20:
stDocName = "MyDoc"
30:
DoCmd.openform stDocName, acFormDS, , stLinkCriteria
Exit_mySUB:
Exit Sub
Err_mySUB:
MsgBox Err.Number & ": " & Err.Description & " (" & Erl & ")"
Resume Exit_mySUB
End Sub
我的解決方案如下:
On Error GoTo {PROCEDURE_NAME}_Error
{PROCEDURE_BODY}
On Error GoTo 0
Exit {PROCEDURE_TYPE}
{PROCEDURE_NAME}_Error:
debug.print "#" & Err.Number, Err.description, "l#" & erl, "{PROCEDURE_NAME}", "{MODULE_NAME}"
然后,通過單擊MZ-Tools菜單中的相應按鈕,可以將此標准錯誤代碼自動添加到所有過程和功能中。 你會注意到我們在這里引用VBA標准庫中的隱藏和未記錄的函數,'Erl',它代表'錯誤行'。 你說對了! 如果您要求MZ-Tools自動為您的代碼行編號,那么'Erl'將為您提供發生錯誤的行號。 您將在即時窗口中獲得錯誤的完整描述,例如:
#91, Object variable or With block variable not set, l# 30, addNewField, Utilities
當然,一旦你意識到系統的興趣,你就可以想到一個更復雜的錯誤處理程序,它不僅會在調試窗口中顯示數據,還會:
意味着在用戶級別生成的每個錯誤都可以存儲在文件或表中,機器或網絡上的某個位置。 我們是否正在討論構建與VBA一起使用的自動錯誤報告系統 ?
你總是可以像Chip Pearson那樣推出自己的工具。 VBA實際上可以通過Microsoft Visual Basic for Applications Extensibility 5.3 Library訪問它自己的IDE。 我編寫了一些類模塊,可以更輕松地與自己合作。 它們可以在Code Review SE上找到。
我用它來插入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是表單的名稱):
MyModule.InsertErrHandling "Form_Form1"
它會改變你在Form1中的頌歌:
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
現在在模塊中創建一個Sub,它將顯示錯誤對話框,您可以在其中添加將錯誤插入到文本文件或數據庫中:
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
如果proc中已存在“On Error”語句,則此代碼不會進入錯誤處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.