ログ+例外テンプレ
つまずいた時に「何が起きたか」を残しつつ、止めずに安全に終わらせる。そのために、ログ出力と例外(エラー)処理をワンセットで使えるテンプレートをまとめました。初心者でもすぐ使える形で、例題付きで説明します。
基本の考え方と使い分け
- 目的:
- エラーが起きても止まらず「記録」「後始末」「通知」を行う。
- 出力先の選択:
- 開発中: Immediateウィンドウ(Debug.Print)。
- 運用: ファイル出力 or シート出力(監査・追跡用)。
- ログレベル(おすすめ):
- INFO: 開始/終了/要点。
- WARN: 想定外だが継続可能。
- ERROR: 例外発生・中断・復旧内容。
- DEBUG: 詳細トレース(開発時のみ)。
テンプレ1:最小構成(即使える)
' すぐ使える軽量ロガー(Immediate出力)
Sub Log(ByVal level As String, ByVal msg As String)
Debug.Print Format(Now, "yyyy-mm-dd HH:NN:SS") & " [" & level & "] " & msg
End Sub
' 例外処理つきの基本形
Sub RunBasic()
On Error GoTo ErrHandler
Log "INFO", "処理開始"
' 本処理(例:レポート生成)
Worksheets("Report").Range("A1").Value = "作成日: " & Date
Log "DEBUG", "Report!A1 に日付を書き込み"
' 故意にエラー
Worksheets("NoSheet").Activate
Log "INFO", "処理正常終了"
Exit Sub
ErrHandler:
Log "ERROR", "Err " & Err.Number & " | " & Err.Description
' 必要なら後始末(ファイルクローズ、状態復元など)
End Sub
VB- ポイント:
- 開始/終了を必ず記録。
- 例外発生時に番号と説明を残す。
- 後始末はエラー側でまとめると安全。
テンプレ2:共有ロガー(レベル+出力切替)
' 標準モジュール: Logger.bas
Public Enum LogLevel
LOG_DEBUG = 1
LOG_INFO = 2
LOG_WARN = 3
LOG_ERROR = 4
End Enum
Public CURRENT_LOG_LEVEL As LogLevel
Public OUTPUT_TO_FILE As Boolean
Public LOG_PATH As String
Public Sub LogInit(Optional lvl As LogLevel = LOG_INFO, _
Optional toFile As Boolean = False, _
Optional path As String = "C:\temp\vba.log")
CURRENT_LOG_LEVEL = lvl
OUTPUT_TO_FILE = toFile
LOG_PATH = path
End Sub
Public Sub LogWrite(ByVal lvl As LogLevel, ByVal msg As String)
If lvl < CURRENT_LOG_LEVEL Then Exit Sub
Dim prefix As String
Select Case lvl
Case LOG_DEBUG: prefix = "DEBUG"
Case LOG_INFO: prefix = "INFO "
Case LOG_WARN: prefix = "WARN "
Case LOG_ERROR: prefix = "ERROR"
End Select
Dim line As String
line = Format(Now, "yyyy-mm-dd HH:NN:SS") & " [" & prefix & "] " & msg
If OUTPUT_TO_FILE Then
Dim fso As Object, ts As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.OpenTextFile(LOG_PATH, 8, True) ' 8=追記
ts.WriteLine line
ts.Close
Else
Debug.Print line
End If
End Sub
Public Sub HandleError(ByVal procName As String)
LogWrite LOG_ERROR, "Proc=" & procName & _
" | Err " & Err.Number & " | " & Err.Description
Err.Clear
End Sub
VB' 使い方例
Sub RunWithSharedLogger()
On Error GoTo ErrHandler
LogInit LOG_DEBUG, True, "C:\temp\run.log" ' レベル=DEBUG, 出力=ファイル
LogWrite LOG_INFO, "日次処理開始"
' …処理…
LogWrite LOG_DEBUG, "入力件数=123"
' 故意にエラー
Worksheets("NoSheet").Activate
LogWrite LOG_INFO, "日次処理正常終了"
Exit Sub
ErrHandler:
HandleError "RunWithSharedLogger"
End Sub
VB- ポイント:
- レベルで絞り込み(運用はINFO以上、開発はDEBUG)。
- 出力先切替(Immediate/ファイル)で使い回し。
- 共通エラーハンドラに処理名を渡して特定しやすくする。
テンプレ3:例外境界(Try風)と後始末(Finally風)
' Try-Finally風のパターン(VBAにはFinallyがないため、手動で後始末を保証)
Sub TryFinallyExample()
Dim fso As Object, ts As Object, ok As Boolean
On Error GoTo ErrHandler
Log "INFO", "ファイル書き込み開始"
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.OpenTextFile("C:\temp\out.txt", 2, True) ' 2=書き込み
ts.WriteLine "処理開始: " & Now
' 本処理…
ts.WriteLine "データ: 123"
ok = True
CleanUp:
' 後始末(必ず通る)
On Error Resume Next
If Not ts Is Nothing Then ts.Close
Set ts = Nothing: Set fso = Nothing
On Error GoTo 0
If ok Then
Log "INFO", "ファイル書き込み正常終了"
Else
Log "WARN", "ファイル書き込みは後始末済み(エラーあり)"
End If
Exit Sub
ErrHandler:
Log "ERROR", "Err " & Err.Number & " | " & Err.Description
ok = False
GoTo CleanUp
End Sub
VB- ポイント:
- CleanUpラベルで「Finally風」の後始末を保証。
- 成否フラグを使って終了ログのレベルを切り替える。
テンプレ4:1件ずつの堅牢処理(Resume Next+集計)
Sub RobustPerItem()
Dim ws As Worksheet: Set ws = Worksheets("Input")
Dim cell As Range
Dim okCount As Long, ngCount As Long
Log "INFO", "行単位処理開始"
For Each cell In ws.Range("A1:A20")
On Error Resume Next
' 各行の小さな失敗はスキップして集計
cell.Offset(0, 1).Value = CLng(cell.Value) ' ここで失敗する可能性
If Err.Number <> 0 Then
Log "WARN", "変換失敗 at " & cell.Address & " | " & Err.Description
Err.Clear
ngCount = ngCount + 1
Else
okCount = okCount + 1
End If
On Error GoTo 0
Next
Log "INFO", "行単位処理終了 OK=" & okCount & " NG=" & ngCount
End Sub
VB- ポイント:
- Resume Nextは「1件失敗でも全体継続」したい時に有効。
- 必ずErr判定+Err.Clearで後続への影響を断つ。
- 最後に件数集計をログ出力。
例題で練習(すぐ試せる)
- 例1: テンプレ1を使って、存在しないシート参照エラーを記録しつつ終了ログを出す。
- 例2: テンプレ2の共有ロガーでレベルをINFOにして、実運用向けファイルログを作る。
- 例3: テンプレ3のCleanUpを使って、ファイル出力やADO接続を安全に後始末する。
- 例4: テンプレ4でA1:A20を整数変換し、失敗件数をWARNログに残す。
初心者向けポイント(実務で効くコツ)
- 開始・終了ログは必須: 走ったかどうか、どこで終わったかが分かる。
- 例外情報は3点セット: 番号、説明、処理名(関数名)。
- Resume Nextは限定使用: ループ内など「継続が重要」な場面に絞る。
- 後始末は必ず共通化: ファイル/接続/画面状態はCleanUpで確実に戻す。
- 運用時はINFO/WARN/ERRORだけ: DEBUGは開発時のみで十分。
