Excel VBA 逆引き集 | 実務テンプレ完全版(超再利用部品) – 処理ログ自動生成

Excel VBA
スポンサーリンク

ねらい:どのマクロにも「同じ形の処理ログ」を自動で残す

「このマクロ、ちゃんと最後まで動いたのか?」
「どのシートを何件処理したのか?」
「エラーが出たのは何時何分で、どの処理中だったのか?」

こういう“あとから振り返る情報”がないと、トラブル対応も改善も全部「勘」になります。
そこで作っておきたいのが、「どのマクロからでも呼べる共通の処理ログテンプレ」です。

ここで目指すのは、次のような世界です。

マクロの開始時に「開始ログ」を1行書く。
重要な処理の前後で「イベントログ」を書く。
終了時に「正常終了」か「エラー終了」かをログに残す。

そして、そのためのコードは一度だけ作り、あとはどのマクロでも同じ呼び方で使えるようにします。


全体設計:Logシート+共通ログモジュールという二段構え

ログを残す場所の決め方

まず、「処理ログを書き込む専用シート」を1枚決めます。
名前は分かりやすく LogProcessLog などにしておくと良いです。

このシートには、次のような列を持たせます。

A列:日時(タイムスタンプ)
B列:レベル(INFO / WARN / ERROR など)
C列:モジュール名(どのマクロからのログか)
D列:イベント名(開始、終了、ステップ名など)
E列:メッセージ(件数や対象シート名などの詳細)

この「列構成」を固定しておくことで、どのマクロのログも同じフォーマットで蓄積されていきます。

ログの書き込みは「共通プロシージャ」だけに集約する

ログを書き込むコードを、各マクロの中にバラバラに書いてしまうと、
フォーマットが揃わないし、修正も大変になります。

そこで、「ログを書くのはこのプロシージャだけ」と決めてしまいます。

たとえば LogWrite level, moduleName, eventName, message のような形です。
マクロ側は、このプロシージャを呼ぶだけ。
どのセルにどう書くかは、共通モジュールの中に閉じ込めます。


コア部品:1行のログを書き込む共通プロシージャ

ログ書き込みの基本形

まずは、一番大事な「1行のログを書く」プロシージャです。

' ModLogger.bas
Option Explicit

Public Sub LogWrite( _
        ByVal level As String, _
        ByVal moduleName As String, _
        ByVal eventName As String, _
        Optional ByVal message As String = "")
    
    Dim ws As Worksheet
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("Log")
    On Error GoTo 0
    
    If ws Is Nothing Then
        Set ws = ThisWorkbook.Worksheets.Add
        ws.Name = "Log"
        ws.Range("A1:E1").Value = Array("DateTime", "Level", "Module", "Event", "Message")
    End If
    
    Dim nextRow As Long
    nextRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
    
    ws.Cells(nextRow, 1).Value = Now
    ws.Cells(nextRow, 2).Value = UCase$(level)
    ws.Cells(nextRow, 3).Value = moduleName
    ws.Cells(nextRow, 4).Value = eventName
    ws.Cells(nextRow, 5).Value = message
End Sub
VB

初心者向けにポイントをかみ砕きます。

最初に Log シートを取得しようとします。
存在しなければ、新しく追加して、1行目にヘッダーを書きます。
次に、A列の最終行を探して、その1つ下の行番号を nextRow として求めます。
その行に、日時、レベル、モジュール名、イベント名、メッセージを書き込みます。

これで、「LogWrite を呼ぶだけで、Log シートの末尾に1行追加される」という仕組みができます。


開始・終了・エラー用の“お決まりラッパー”を用意する

開始ログ専用のプロシージャ

毎回「開始」と書くのも面倒なので、開始用のラッパーを用意します。

Public Sub LogStart(ByVal moduleName As String, Optional ByVal message As String = "")
    LogWrite "INFO", moduleName, "START", message
End Sub
VB

これで、マクロの先頭に

LogStart "ImportCustomer", "顧客CSV取込開始"
VB

と書くだけで、「INFO / ImportCustomer / START / 顧客CSV取込開始」というログが1行残ります。

正常終了ログ専用のプロシージャ

同じように、正常終了用も作ります。

Public Sub LogEnd(ByVal moduleName As String, Optional ByVal message As String = "")
    LogWrite "INFO", moduleName, "END", message
End Sub
VB

マクロの最後に

LogEnd "ImportCustomer", "顧客CSV取込正常終了"
VB

と書けばOKです。

エラー用のプロシージャ

エラー時には、レベルを ERROR にして、エラー番号や内容も残したいですよね。

Public Sub LogError(ByVal moduleName As String, ByVal eventName As String, ByVal errObj As ErrObject)
    Dim msg As String
    msg = "ErrNumber=" & errObj.Number & ", Description=" & errObj.Description
    LogWrite "ERROR", moduleName, eventName, msg
End Sub
VB

これを使うときは、マクロ側でエラー処理をこう書きます。

Sub ImportCustomer()
    Const MODULE_NAME As String = "ImportCustomer"
    On Error GoTo ErrHandler
    
    LogStart MODULE_NAME, "顧客CSV取込開始"
    
    ' ここに本処理を書く
    
    LogEnd MODULE_NAME, "顧客CSV取込正常終了"
    Exit Sub
    
ErrHandler:
    LogError MODULE_NAME, "MAIN", Err
    MsgBox "エラーが発生しました。ログを確認してください。", vbExclamation
End Sub
VB

重要なのは、「エラーが起きても、どのモジュールのどのタイミングで落ちたかがログに残る」ことです。


例題:顧客CSV取込マクロに処理ログを組み込む

想定する処理の流れ

顧客CSVを取り込むマクロを例にします。

CSVを開く。
顧客データを読み込む。
顧客マスタシートに書き込む。

この3ステップの前後でログを残してみます。

コード例

Sub ImportCustomer()
    Const MODULE_NAME As String = "ImportCustomer"
    On Error GoTo ErrHandler
    
    LogStart MODULE_NAME, "顧客CSV取込開始"
    
    LogWrite "INFO", MODULE_NAME, "OPEN_CSV", "顧客CSVを開きます"
    ' CSVを開く処理を書く
    
    LogWrite "INFO", MODULE_NAME, "READ_DATA", "顧客データを読み込みます"
    ' データ読み込み処理を書く
    
    LogWrite "INFO", MODULE_NAME, "WRITE_MASTER", "顧客マスタに書き込みます"
    ' マスタ書き込み処理を書く
    
    LogEnd MODULE_NAME, "顧客CSV取込正常終了"
    Exit Sub
    
ErrHandler:
    LogError MODULE_NAME, "MAIN", Err
    MsgBox "顧客取込中にエラーが発生しました。", vbExclamation
End Sub
VB

このマクロを1回実行すると、Log シートには例えばこんな行が並びます。

日時 / INFO / ImportCustomer / START / 顧客CSV取込開始
日時 / INFO / ImportCustomer / OPEN_CSV / 顧客CSVを開きます
日時 / INFO / ImportCustomer / READ_DATA / 顧客データを読み込みます
日時 / INFO / ImportCustomer / WRITE_MASTER / 顧客マスタに書き込みます
日時 / INFO / ImportCustomer / END / 顧客CSV取込正常終了

もし途中でエラーが起きれば、ERROR 行が追加されます。


重要ポイントの深掘り:処理ログを“本当に役に立つ”形にする工夫

「モジュール名」を必ず定数で持つ

毎回文字列で "ImportCustomer" と書いていると、タイプミスのリスクがあります。
必ず Const MODULE_NAME As String = "ImportCustomer" のように定数で持ち、
ログ呼び出しではその定数を使うようにすると、ログのモジュール名がブレません。

これが後で「どのマクロがどれくらい動いているか」を集計するときに効いてきます。

「イベント名」を粒度よく切る

全部「MAIN」だけだと、どこで時間がかかっているのか、どこで落ちたのかが分かりません。
処理の大きな塊ごとに、イベント名を分けておくと良いです。

OPEN_CSV
READ_DATA
WRITE_MASTER
VALIDATE_DATA

など、あなた自身が見て「ここで止まっているな」と分かる粒度で切るのがコツです。

件数や対象をメッセージに入れる

メッセージ欄は、単なる説明文だけでなく、「数字」を入れると一気に価値が上がります。

例えば、

読み込んだ件数
スキップした件数
エラーになった件数
対象シート名やファイル名

などを message に入れておくと、後からログをフィルタして「この日、このマクロは何件処理したのか」がすぐに分かります。

例として、件数付きのログを書いてみます。

Dim cnt As Long
cnt = 1234
LogWrite "INFO", MODULE_NAME, "READ_DATA", "顧客データ読み込み件数=" & cnt

ログシートが肥大化してきたら

長く運用していると、Log シートの行数がどんどん増えていきます。
数万行を超えてきたら、定期的に「月ごとに別ブックに退避する」などの運用ルールを決めておくと良いです。

簡易的には、「古い行を削除するマクロ」を用意しておくのも一つの手です。


まとめ:処理ログ自動生成は「LogWrite を共通化する」だけで一気に楽になる

今回のテンプレの核は、とてもシンプルです。

Log シートという“ログ専用の置き場”を決める。
LogWrite という「1行のログを書く共通プロシージャ」を作る。
各マクロでは、開始・終了・重要ステップ・エラーのタイミングで LogStart / LogEnd / LogWrite / LogError を呼ぶだけにする。

これを一度仕組みとして作ってしまえば、
新しいマクロを書くたびに「ログどうしようかな…」と悩む必要はなくなります。

タイトルとURLをコピーしました