きなこSHOW

日々の戯言

【VBA】エラーメッセージをログ出力するExcel & Accessサンプル

ExcelやAccessのツールでエラーが発生したときなどに、ログを出力するサンプルコードを紹介します。

どんなに正確に厳密にコーディングしていたとしてもエラーは起こるものです。
On Error Goto (行ラベル)で飛ばした先でメッセージを表示させても、ユーザがよく読まずに[OK]ボタンで閉じてしまって、「なんかエラーメッセージ表示されてました」とメールで叱られた...多くの開発者の方が経験しているのではないでしょうか。
何が起きたのか、どこで起きたのか。
主に自分を守るためにエラーの内容をログ出力しています。

エラーメッセージをログファイルに出力するコードと呼び出し例

ログ出力プロシージャ

以下のコードをコピーして、標準モジュールに貼り付けてください。
Excelのプロジェクトで使用する場合は、ファイル名を作成する箇所の「(Excelの場合)」の行を残して、「(Access...)」の行を削除、Accessで使用する場合はAccessを残してExcelの行を削除してください。

'***************************************************************************
'名称 :gOutputLog
'機能 :エラーメッセージをログファイルに出力する
'引数 :vsMsg     (I )    String        メッセージ文字列
'作成 :2013/05/07 kinacco
'更新 :
'***************************************************************************
Public Sub gOutputLog(ByVal vsMsg As String)
On Error GoTo EXIT_SEC
Dim liFileNo        As Integer  'ファイル番号変数
Dim lsWork          As String
Dim lsFilePath      As String

    '--- ファイル名を作成する ---
    lsWork = CurrentProject.FullName   '(Accessの場合)
    lsWork = ThisWorkbook.FullName     '(Excelの場合)
    lsFilePath = Left(lsWork, InStrRev(lsWork, ".", , vbTextCompare) - 1) & "_" & Format(Now(), "YYYYMMDD") & ".txt"
    
    '--- ファイルOPEN ---
    liFileNo = FreeFile()
    Open lsFilePath For Append As #liFileNo

    '--- vsMsgから改行コードを削除する ---
    vsMsg = Replace$(vsMsg, vbCrLf, vbTab)
    vsMsg = Replace$(vsMsg, vbLf, vbTab)
    vsMsg = Replace$(vsMsg, vbCr, vbTab)

    '--- vsMsgの内容をファイルを出力する ---
    Print #liFileNo, Date & " " & Time & " " & vsMsg

EXIT_SEC:
On Error Resume Next

    Close #liFileNo
    
End Sub

本当はファイルの先頭行に出力したいんですけどね。
そうするにはいったんメモリに読み込んでおく必要があって、メモリ不足のときなんかはログ出力できなくなりそうなんで、こんな感じになりました。

呼び出し例

呼び出し方法は簡単です。
On Error Goto の飛び先で、プロシージャ名やErr.Descriptionなどの情報をString型の変数に格納して、それを当関数(gOutputLog)の引数に渡してやるだけなので、渡す内容はお好きにアレンジすると良いと思います。
しれっと別の記事のサンプルコードの中でも使っています。
引数に出力したい文言を渡してやるだけなので、エラー処理ブロック以外で呼び出す事もできます。

Private Function Function名 As Boolean
On Error GoTo ERR_SEC
Dim lbRet	As Boolean
Dim lsMsg	As String

	'--- 初期値セット ---
	lbRet = False
	lsMsg = ""

	'(なにかしらの処理)
	
	'--- 正常終了 ---
	lbRet = True

EXIT_SEC:
On Error Resume Next
    
    (Function名) = lbRet
    
    Exit Function

ERR_SEC:
    lsMsg = "予期せぬエラーが発生しました。" & vbCrLf & _
            "プロシージャ名:(Function名)" & vbCrLf & _
            "エラー番号:" & Err.Number & vbCrLf & _
            "エラー内容:" & Err.Description
    Call gOutputLog(lsMsg)
    Resume EXIT_SEC
End Function

(Function名)の部分にプロシージャ名を記載しておけば、どのプロシージャでエラーが発生したのかをログに残すことができるので原因調査が容易になります。
このログ出力プロシージャはエラー発生時に限らずいつでも実行できるので、例えばデバッグ中に変数の値をファイル出力して確認するなど、様々な用途に使えます。

Call gOutputLog("F_Sample 呼び出し前" & sValue)
sValue = F_Sample(sValue)
Call gOutputLog("F_Sample 呼び出し後" & sValue)

ツール開発のお役に立てれば幸いです。