いつものように、「On Error Goto」ステートメントを使ってエラーハンドラを作成し、そこに数行のクリーニングコードを記述してエラーメッセージを表示させていますが、今度は、エラーが発生した正確な行を示すデフォルトハンドラの快適さを失いたくありません。どうすればいいのでしょうか?
よろしくお願いします。
このコードは、あなたが望んでいることを実現しています(行番号に注意してください)。
Sub a()
10: On Error GoTo ErrorHandler
20: DivisionByZero = 1 / 0
30: Exit Sub
ErrorHandler:
41: If Err.Number <> 0 Then
42: Msg = "Error # " & Str(Err.Number) & " was generated by " _
& Err.Source & Chr(13) & "Error Line: " & Erl & Chr(13) & Err.Description
43: MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
44: End If
50: Resume Next
60: End Sub
実行すると、期待通りのMsgBoxが表示されます。
.
そして、悪いニュースがあります。 行番号は古いバージョンのBasicの名残です。行番号は古いバージョンのBasicの名残で、通常はプログラミング環境が行番号の挿入や更新を行います。VBAやその他の最新バージョンでは、この機能は失われています。
しかし、こちらには、行番号を入力する手間を省き、自動的に行番号を追加する方法がいくつかありますが、どれも多かれ少なかれ面倒なものであり、商用ではありません。
以上、よろしくお願いします。
もっと簡単な方法があります。単純に、あなたが行っているエラータイプと一致しない場合は、エラーハンドラーでエラーハンドラーを無効にして再開します。
以下のハンドラーは、各エラータイプをチェックして、マッチするものがなければ、エラーレジュームを通常のVBA(GoTo 0など)に戻してコードを再開し、コードを再実行しようとすると、通常のエラーブロックがポップアップします。
On Error GoTo ErrorHandler
x = 1/0
ErrorHandler:
if Err.Number = 13 then ' 13 is Type mismatch (only used as an example)
'error handling code for this
end if
If err.Number = 1004 then ' 1004 is Too Large (only used as an example)
'error handling code for this
end if
On Error GoTo 0
Resume
この回答では、「デバッグ」ボタンについては触れていません(あなたの次の質問の方法のようなことをするには、フォームを設計し、その上でボタンを使用しなければなりません)。しかし、この部分については触れています。
エラーが発生した行を正確に示してくれるデフォルトのハンドラの快適さを失いたくありません。
最初に、あなたはこの機能をプロダクションコードでは使用しないと仮定します。私は、デバッグを示すためにコンパイラフラグを使用しています。そうすれば、プログラムのトラブルシューティングをしているときに、問題を引き起こしている行を簡単に見つけることができます。
# Const IsDebug = True
Sub ProcA()
On Error Goto ErrorHandler
' Main code of proc
ExitHere:
On Error Resume Next
' Close objects and stuff here
Exit Sub
ErrorHandler:
MsgBox Err.Number & ": " & Err.Description, , ThisWorkbook.Name & ": ProcA"
#If IsDebug Then
Stop ' Used for troubleshooting - Then press F8 to step thru code
Resume ' Resume will take you to the line that errored out
#Else
Resume ExitHere ' Exit procedure during normal running
#End If
End Sub
注意:Resume
の例外は、エラー処理ルーチンを持たないサブプロシージャーでエラーが発生した場合で、Resume
はエラーが発生したサブプロシージャーを呼び出したこのプロシージャーの行に移動します。しかし、エラーが再び発生するまでは、F8を使って、サブプロシージャの中に入ったり、サブプロシージャを通過したりすることができます。サブプロシージャが長すぎてそれすら面倒な場合は、サブプロシージャが独自のエラー処理ルーチンを持つべきでしょう。
これには複数の方法があります。小さなプログラムでトラブルシューティングをするときには、MsgBoxステートメントの直後に以下の行を入れることがあります。
Resume ExitHere ' Normally exits during production
Resume ' Never will get here
Exit Sub
次のステートメントのポインタをその行にドラッグするか、その行にカーソルがある状態で CtrlF9を押すなどして、ステップスルーで次の実行行として設定しない限り、Resumeステートメントには到達しません。
これらの概念を説明した記事はこちらです。VBAでエラーを処理するための5つのヒントです。 最後に、もしあなたがVBAを使っていて、Chip Pearson'氏の素晴らしいサイトをまだ発見していないのであれば、彼はError Handling In VBAを説明したページを持っています。