これは実際の質問よりも観察です。MS-Access(および一般にVBA)には、エラー処理コードを自動的に生成でき、エラーが発生したときに行番号を表示できるツールが必死に欠けています。解決策を見つけましたか?それは何ですか?数年前にこの基本的な問題に対する正しい答えを見つけてから、何百時間も節約できたことに気づきました。この非常に重要な問題に対するあなたのアイデアと解決策を知りたいと思います。
私の解決策は次のとおりです。
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との連携について話しているのですか?
「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
Chip Pearson のように、いつでも自分のツールをロールできます。 VBAは実際にそれ自体にアクセスできますIDE Microsoft Visual Basic for Applications Extensibility 5.3 Library 。私は自分自身での作業を容易にするいくつかのクラスモジュールを作成しました。それらは 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の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
エラーダイアログを表示し、テキストファイルまたはデータベースへのエラーの挿入を追加できる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
プロシージャにすでに「OnError」ステートメントがある場合、このコードはエラー処理を入力しません。