【VBA】エラー発生時にログ記録+メール通知する方法(コピペOK)

VBA
スポンサーリンク

記事ID: 178
タイトル: 【VBA】エラー発生時にログ記録+メール通知する方法(コピペOK)
カテゴリ: 外部連携
一次キーワード: VBA ログ管理 エラー通知 メール
想定読者: VBAマクロが本番で止まって原因が分からず困っている実務担当者
検索意図: VBAでエラーが起きたときにログを残してメールで通知したい
読者の悩み(1文): マクロがエラーで止まっても原因が分からず、しかも気づくのが翌朝になることがある
読了後にできること(1文): VBAをコピペして実行するだけで、エラー発生時にログファイルへ自動記録し、Outlookでメール通知が届く仕組みが作れる
前提条件:
  - Excel版: Excel 2016以降 / Microsoft 365
  - OS: Windows 10/11
  - 保存形式: .xlsm(マクロ有効ブック)
  - 貼り付け場所: 標準モジュール
  - その他: Outlookインストール済み・初回起動済み(メール通知を使う場合)
  - 実行方法: Alt + F8 → マクロ実行
更新日: 2026-03-25

スポンサーリンク

この記事でできること

VBAでエラーが発生したとき、ログファイルに自動記録し、さらにOutlookでメール通知できるようになる。

自分も以前、夜間に回していた集計マクロが途中で止まっていて、翌朝出社して初めて気づいた。原因も分からず、どこまで処理が終わったのかも不明。正直あのときは焦った。ログを残す仕組みを入れてからは、エラーが起きても「いつ・どこで・何が」が即座に分かるようになって、対応スピードが格段に変わった。

この記事で、同じ悩みを抱えている人がサクッとエラーログ+通知の仕組みを導入できるようになればうれしい。

  • 対象:マクロのエラー原因が分からなくて困っている人、VBAのエラー処理(On Error)を使ったことがある人
  • 所要時間:コピペ → 実行まで約10分(目安)

どんな場面で使う?

  • 夜間や定時実行のマクロがエラーで止まったとき、原因をすぐ特定したいとき
  • エラー発生を即座にメールで通知して、対応の遅れを防ぎたいとき
  • 「いつ・どこで・何のエラーが起きたか」をログファイルに自動記録して追跡可能にしたいとき
  • 一時的なエラー(ネットワーク切断など)に対して自動リトライする仕組みを入れたいとき

完成イメージ(Before / After)

Before(実行前)

マクロがエラーで停止。原因不明。いつ止まったかも分からない。


実行時エラー '1004':
アプリケーション定義またはオブジェクト定義のエラーです。
→ [終了] [デバッグ]

After(実行後)

エラーが発生すると、ログファイルに詳細が自動記録され、Outlookでメール通知が届く。

ログファイル(error_log.txt)の例:


[2026-03-25 09:15:32] ERROR | プロシージャ: 月次集計処理 | エラー番号: 1004 | 内容: アプリケーション定義またはオブジェクト定義のエラーです。 | 行の目安: Range操作
[2026-03-25 09:15:32] INFO  | メール通知を送信しました

メール通知の例:


件名:【VBAエラー】月次集計処理でエラーが発生しました
本文:
  発生日時:2026-03-25 09:15:32
  プロシージャ:月次集計処理
  エラー番号:1004
  エラー内容:アプリケーション定義またはオブジェクト定義のエラーです。
  ブック名:月次集計.xlsm

実行前の準備

バックアップを取る

既存のマクロに組み込む場合は、先にファイルをコピーしてバックアップを取ること。

Excelをマクロ有効ブック(.xlsm)で保存する

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を 「Excel マクロ有効ブック (*.xlsm)」 に変更して保存

Outlookの起動を確認する(メール通知を使う場合)

メール通知機能を使う場合は、Outlookがインストール済みで起動していること。ログファイル出力だけなら不要。

手順(コピペ → 実行まで約10分)

1. VBE(コードを書く画面)を開く

Alt + F11 キーを押すとVBE(Visual Basic Editor)が開く。

2. 標準モジュールを挿入する

  1. VBEのメニュー「挿入」→「標準モジュール」をクリック
  2. 右側に白い画面(コードウィンドウ)が表示される

3. コードを貼り付けて実行する

  1. 下の「コード(基本版)」をコピーして、コードウィンドウに貼り付ける
  2. Alt + F8 を押す(または VBE上で F5
  3. 「SampleWithErrorLog」を選択して「実行」
  4. わざとエラーを起こすテストコードなので、ブックと同じフォルダに error_log.txt が作成されることを確認する

コード(基本版)– エラー発生時にログファイルへ記録

まずはこれだけで動く。On Errorでエラーをキャッチし、テキストファイルにログを書き出す。マクロの実行ログをファイルに自動記録する方法の応用版。


Sub SampleWithErrorLog()

    Dim ws As Worksheet

    On Error GoTo ErrHandler

    ' ===== ここに通常の処理を書く =====
    ' (テスト用:存在しないシートを指定してわざとエラーを起こす)
    Set ws = ThisWorkbook.Sheets("存在しないシート")

    ' ===== 通常処理ここまで =====

    MsgBox "処理が正常に完了しました。", vbInformation
    Exit Sub

ErrHandler:
    ' エラー情報をログファイルに書き出す
    Call WriteErrorLog("SampleWithErrorLog", Err.Number, Err.Description)

    MsgBox "エラーが発生しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description & vbCrLf & vbCrLf & _
           "詳細はログファイルを確認してください。", vbCritical

End Sub

Sub WriteErrorLog(ByVal procName As String, _
                  ByVal errNum As Long, _
                  ByVal errDesc As String)

    Dim logPath As String
    Dim fileNum As Integer
    Dim logLine As String

    ' ログファイルのパス(ブックと同じフォルダに出力)
    logPath = ThisWorkbook.Path & "\error_log.txt"

    ' ログ1行を組み立てる
    logLine = "[" & Format(Now, "yyyy-mm-dd hh:nn:ss") & "] ERROR" & _
              " | プロシージャ: " & procName & _
              " | エラー番号: " & errNum & _
              " | 内容: " & errDesc

    ' ファイルに追記(Append モード)
    fileNum = FreeFile
    Open logPath For Append As #fileNum
    Print #fileNum, logLine
    Close #fileNum

End Sub

ポイント:

  • On Error GoTo ErrHandler でエラーをキャッチし、処理を ErrHandler ラベルに飛ばす
  • WriteErrorLog を別プロシージャにしているので、どのマクロからでも Call WriteErrorLog(...) で呼び出せる
  • ログファイルは Append モード(追記)なので、過去のログが消えない
  • エラー処理(On Error)で止まらないマクロを作る方法も参考にすると理解が深まる

コード(実務版)– エラー詳細+自動リトライ+メール通知+日次ログローテーション

自分はこの実務版を定時実行の集計マクロに組み込んでいる。夜間にエラーが起きても翌朝メールで気づけるので、出社してすぐ対応できるようになった。


' ===================================================
' エラーログ+メール通知+リトライ機能付きテンプレート
' ===================================================

' ---------- 設定値(環境に合わせて変更) ----------
Private Const LOG_FOLDER As String = ""          ' 空欄 = ブックと同じフォルダ
Private Const LOG_PREFIX As String = "error_log" ' ログファイル名の接頭辞
Private Const MAX_RETRY As Long = 3              ' 自動リトライ回数
Private Const RETRY_WAIT_SEC As Long = 5         ' リトライ間隔(秒)
Private Const NOTIFY_EMAIL As String = "your-email@example.com" ' 通知先メールアドレス
Private Const LOG_RETENTION_DAYS As Long = 30    ' ログ保持日数(古いログを自動削除)

' ---------- メイン処理(実務版テンプレート) ----------
Sub MainProcessWithFullErrorHandling()

    Dim retryCount As Long
    Dim succeeded As Boolean

    ' --- ログローテーション(古いログを削除) ---
    Call RotateOldLogs

    ' --- リトライ付きメイン処理 ---
    succeeded = False
    retryCount = 0

    Do While retryCount <= MAX_RETRY And Not succeeded
        On Error GoTo RetryHandler

        ' ===== ここに通常の処理を書く(ここから) =====

        ' (テスト用:存在しないシートでわざとエラー)
        Dim ws As Worksheet
        Set ws = ThisWorkbook.Sheets("存在しないシート")

        ' ===== 通常の処理ここまで =====

        succeeded = True  ' ここまで来たら成功

    Loop

    If succeeded Then
        Call WriteLog "INFO", "MainProcess", "処理が正常に完了しました"
        MsgBox "処理が正常に完了しました。", vbInformation
    End If

    Exit Sub

RetryHandler:
    retryCount = retryCount + 1

    If retryCount <= MAX_RETRY Then
        ' --- リトライ可能:ログ記録してリトライ ---
        Call WriteLog "WARN", "MainProcess", _
            "リトライ " & retryCount & "/" & MAX_RETRY & _
            " | エラー番号: " & Err.Number & _
            " | 内容: " & Err.Description

        ' 指定秒数待機してからリトライ
        Call WaitSeconds(RETRY_WAIT_SEC)
        Resume  ' エラーが発生した行を再実行
    Else
        ' --- リトライ上限:ログ記録+メール通知 ---
        Call WriteLog "ERROR", "MainProcess", _
            "リトライ上限到達 | エラー番号: " & Err.Number & _
            " | 内容: " & Err.Description & _
            " | ブック: " & ThisWorkbook.Name

        ' メール通知を送信
        Call SendErrorNotification("MainProcess", Err.Number, Err.Description)

        MsgBox "エラーが発生しました(" & MAX_RETRY & "回リトライ後も失敗)。" & vbCrLf & _
               "エラー番号: " & Err.Number & vbCrLf & _
               "内容: " & Err.Description & vbCrLf & vbCrLf & _
               "管理者にメール通知を送信しました。" & vbCrLf & _
               "ログファイルを確認してください。", vbCritical
    End If

End Sub

' ---------- ログ書き込み(レベル付き) ----------
Sub WriteLog(ByVal logLevel As String, _
             ByVal procName As String, _
             ByVal message As String)

    Dim logPath As String
    Dim fileNum As Integer
    Dim logLine As String
    Dim baseFolder As String

    ' ログフォルダの決定
    If LOG_FOLDER = "" Then
        baseFolder = ThisWorkbook.Path
    Else
        baseFolder = LOG_FOLDER
    End If

    ' 日付ごとのログファイル名(例:error_log_20260325.txt)
    logPath = baseFolder & "\" & LOG_PREFIX & "_" & Format(Now, "yyyymmdd") & ".txt"

    ' ログ行を組み立て
    logLine = "[" & Format(Now, "yyyy-mm-dd hh:nn:ss") & "] " & _
              Format(logLevel, "!@@@@@") & _
              " | プロシージャ: " & procName & _
              " | " & message

    ' ファイルに追記
    fileNum = FreeFile
    Open logPath For Append As #fileNum
    Print #fileNum, logLine
    Close #fileNum

End Sub

' ---------- メール通知(Outlook) ----------
Sub SendErrorNotification(ByVal procName As String, _
                          ByVal errNum As Long, _
                          ByVal errDesc As String)

    Dim olApp As Object
    Dim olMail As Object

    On Error GoTo MailError

    Set olApp = CreateObject("Outlook.Application")
    Set olMail = olApp.CreateItem(0) ' olMailItem = 0

    With olMail
        .To = NOTIFY_EMAIL
        .Subject = "【VBAエラー】" & procName & "でエラーが発生しました"
        .Body = "以下のエラーが発生しました。" & vbCrLf & vbCrLf & _
                "発生日時:" & Format(Now, "yyyy-mm-dd hh:nn:ss") & vbCrLf & _
                "プロシージャ:" & procName & vbCrLf & _
                "エラー番号:" & errNum & vbCrLf & _
                "エラー内容:" & errDesc & vbCrLf & _
                "ブック名:" & ThisWorkbook.Name & vbCrLf & _
                "ブックパス:" & ThisWorkbook.FullName & vbCrLf & vbCrLf & _
                "リトライ回数:" & MAX_RETRY & "回(すべて失敗)" & vbCrLf & vbCrLf & _
                "ログファイルを確認してください。"
        .Display  ' ★ 安全のため下書き表示。自動送信にするなら .Send に変更
    End With

    Call WriteLog "INFO", procName, "メール通知を送信しました(宛先: " & NOTIFY_EMAIL & ")"

    Set olMail = Nothing
    Set olApp = Nothing
    Exit Sub

MailError:
    ' メール送信自体が失敗した場合もログに記録
    Call WriteLog "ERROR", "SendErrorNotification", _
        "メール通知に失敗 | エラー番号: " & Err.Number & _
        " | 内容: " & Err.Description

    Set olMail = Nothing
    Set olApp = Nothing

End Sub

' ---------- 待機処理(リトライ間隔用) ----------
Sub WaitSeconds(ByVal sec As Long)
    Dim endTime As Double
    endTime = Timer + sec
    Do While Timer < endTime
        DoEvents  ' Excel が固まらないようにする
    Loop
End Sub

' ---------- ログローテーション(古いログを削除) ----------
Sub RotateOldLogs()

    Dim baseFolder As String
    Dim fileName As String
    Dim filePath As String
    Dim fileDate As Date

    On Error GoTo RotateError

    If LOG_FOLDER = "" Then
        baseFolder = ThisWorkbook.Path
    Else
        baseFolder = LOG_FOLDER
    End If

    fileName = Dir(baseFolder & "\" & LOG_PREFIX & "_*.txt")

    Do While fileName <> ""
        filePath = baseFolder & "\" & fileName

        ' ファイルの最終更新日を確認
        fileDate = FileDateTime(filePath)

        ' 保持日数を超えたログファイルを削除
        If DateDiff("d", fileDate, Now) > LOG_RETENTION_DAYS Then
            Kill filePath
            Call WriteLog "INFO", "RotateOldLogs", "古いログを削除: " & fileName
        End If

        fileName = Dir()
    Loop

    Exit Sub

RotateError:
    ' ローテーション失敗は致命的ではないので、ログだけ残して続行
    Call WriteLog "WARN", "RotateOldLogs", _
        "ログローテーションに失敗 | エラー番号: " & Err.Number & _
        " | 内容: " & Err.Description

End Sub

追加ポイント(基本版との違い):

機能 基本版 実務版
ログ出力 単一ファイルに追記 日付別ファイル(error_log_20260325.txt)
ログレベル ERRORのみ INFO / WARN / ERROR
リトライ なし 最大3回(間隔5秒、変更可)
メール通知 なし Outlook連携で自動通知
ログローテーション なし 30日超の古いログを自動削除
.Display / .Send .Display(下書き表示)がデフォルト

注意: .Display は下書きとして表示するだけで送信しない。完全自動送信にする場合は .Send に変更するが、送信後は取り消しできないので十分テストしてから切り替えること。Excelからメール自動作成(Outlook連携)も参照。

カスタマイズのヒント

自分の既存マクロに組み込む方法

既存のマクロにエラーログを追加するのは簡単。以下の3ステップだけ。

  1. WriteErrorLog(基本版)または WriteLog + SendErrorNotification(実務版)を標準モジュールに貼り付ける
  2. 既存のマクロに On Error GoTo ErrHandler を追加する
  3. マクロの末尾に ErrHandler: ラベルと Call WriteErrorLog(...) を追加する

Sub 既存のマクロ()
    On Error GoTo ErrHandler    ' ← 追加

    ' ... 既存の処理 ...

    Exit Sub                     ' ← 追加(正常終了時にErrHandlerを飛ばす)

ErrHandler:                      ' ← 追加
    Call WriteErrorLog("既存のマクロ", Err.Number, Err.Description)
    MsgBox "エラーが発生しました。ログを確認してください。", vbCritical
End Sub

よくある落とし穴5選

# 症状 原因 対策
1 ログファイルが作成されない ブックが未保存(ThisWorkbook.Path が空文字)で保存先パスが取得できない ブックを保存してから実行する。または LOG_FOLDER に固定パスを指定する
2 「実行時エラー 429: ActiveX コンポーネントは…」が出る Outlookがインストールされていない、または起動していない Outlookを起動してから実行する。Outlookが使えない環境ではメール通知部分をコメントアウトする
3 ログファイルに書き込めない(権限エラー) ネットワークドライブや読み取り専用フォルダに出力しようとしている ローカルの書き込み可能なフォルダを LOG_FOLDER に指定する
4 リトライしても同じエラーで止まる 一時的な問題ではなく、コードのバグやデータの問題 リトライは「ネットワーク一時切断」「ファイルロック」など一時的な問題向け。根本原因はログを見て修正する
5 日付をまたぐとログが分かれて見づらい 日次ローテーションの仕様 日付別ファイルは検索しやすい利点もある。まとめて見たい場合は LOG_PREFIX を固定ファイル名にして日付を外す

自分もログファイルが作成されない問題で30分悩んだことがある。原因はブックを .xlsm で保存する前に実行していて、ThisWorkbook.Path が空文字だった。保存してから実行したらあっさり解決した。

VBAのエラーログが作成されないときの対処法

「マクロを実行してもログファイルが生成されない」場合、ブックが未保存の状態でThisWorkbook.Pathが空文字になっていることが原因だ。ブックを.xlsmで保存してから実行するか、LOG_FOLDER定数にフルパス(例:"C:\Logs\VBA")を直接指定しよう。

VBAのOutlookメール通知で「ActiveXコンポーネント」エラーが出るときの対処法

「実行時エラー429が出てメールが送れない」場合、Outlookがインストールされていないか起動していないことが原因だ。Outlookを起動してから再実行しよう。Outlookが使えない環境では、メール通知部分をコメントアウトしてログ記録のみで運用する方法もある。

FAQ

Q1. ログファイルの保存先を変えたいのですが?

実務版の LOG_FOLDER 定数にフルパスを指定する。例:Private Const LOG_FOLDER As String = "C:\Logs\VBA"。空欄のままだとブックと同じフォルダに出力される。

Q2. メールを下書きではなく自動送信にしたい場合は?

SendErrorNotification プロシージャ内の .Display.Send に変更する。ただし .Send は送信後に取り消しできないので、テスト用アドレスで十分確認してから本番に適用すること。自分は最初の1週間は .Display のまま運用して問題ないことを確認してから .Send に切り替えた。

Q3. エラーがないときもログを残したいのですが?

実務版の WriteLog"INFO" レベルで処理開始・終了のログを追加するとよい。例:Call WriteLog "INFO", "MainProcess", "処理を開始しました"マクロの実行ログをファイルに自動記録する方法で基本的なログ記録の考え方を詳しく解説している。

Q4. 複数のマクロでエラーログを共通化できますか?

できる。WriteErrorLog(基本版)や WriteLog(実務版)は独立したプロシージャなので、どのマクロからでも Call WriteLog "ERROR", "プロシージャ名", "メッセージ" で呼び出せる。マクロから別のマクロを呼び出して処理を分割する方法も参考になる。

Q5. Outlook以外のメール(Gmail等)で通知を送れますか?

VBA標準の機能ではOutlook連携が最も手軽。Gmail等を使いたい場合はCDO(Collaboration Data Objects)を使う方法があるが、SMTP認証やセキュリティ設定が必要で手順が複雑になる。まずはOutlook連携で始めるのがおすすめ。

まとめ

この記事では、VBAでエラー発生時にログファイルへ自動記録し、Outlookでメール通知する方法を紹介した。

  • 基本版:On Errorでキャッチ → テキストファイルにログ追記(最小構成)
  • 実務版:日付別ログ+ログレベル+自動リトライ+Outlookメール通知+日次ログローテーション

エラー処理の基本を押さえたい場合は、エラー処理(On Error)で止まらないマクロを作る方法を先に読んでおくと理解しやすい。ログ記録の基本はマクロの実行ログをファイルに自動記録する方法で解説している。

定時実行と組み合わせたい場合は、指定時刻にマクロを自動実行する方法を参照。メール送信のバリエーションを増やしたい場合はExcelファイルをOutlookメールに自動添付して送信する方法も役立つ。

次にやりたくなること

コメント

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