バッチ処理の完了・失敗を自動でメール通知する仕組みを、Excel VBA+Outlookで作る例です。構成は「処理→結果集計→メール送信→ログ記録」。安全に運用できるよう、リトライ・例外処理・スケジューリングまで含めます。
アーキテクチャと処理の流れ
- 構成:
- バッチ本体: データ処理(例: シート行の更新、ファイル入出力)。
- 通知モジュール: Outlookでメール送信(成功/失敗/サマリ)。
- ロギング: シート/CSVに開始時刻、終了時刻、件数、失敗理由を記録。
- スケジュール: 指定時刻に自動実行(ExcelのOnTimeまたはWindows タスクスケジューラ)。
- フロー:
- 1. 初期化: ログ開始、設定読み込み(宛先・件名テンプレ)。
- 2. 実行: バッチ処理ループ(行単位・ファイル単位)。
- 3. 集計: 成功/失敗件数、失敗一覧。
- 4. 通知: 成功メール+失敗詳細、致命的エラーの場合は即時失敗通知。
- 5. 記録: ログ出力、再実行のための失敗行マーキング。
コード例(Excel VBA+Outlook)
モジュール構成
- Module1: エントリーポイントとスケジュール
- ModuleMail: Outlook送信用の汎用関数
- ModuleBatch: バッチ本体、集計、ロギング
ModuleMail(Outlook 送信)
' 参照設定なしでも動く「Late Binding」推奨
' 参考: Outlook立ち上げ済みでなくても起動される
Public Function SendMail( _
ByVal toAddr As String, _
ByVal subjectText As String, _
ByVal bodyText As String, _
Optional ByVal ccAddr As String = "", _
Optional ByVal bccAddr As String = "", _
Optional ByVal attachPath As String = "" _
) As Boolean
On Error GoTo ErrHandler
Dim olApp As Object, olMail As Object
Set olApp = CreateObject("Outlook.Application")
Set olMail = olApp.CreateItem(0) ' olMailItem = 0
With olMail
.To = toAddr
If Len(ccAddr) > 0 Then .CC = ccAddr
If Len(bccAddr) > 0 Then .BCC = bccAddr
.Subject = subjectText
.Body = bodyText
If Len(attachPath) > 0 Then
If Dir(attachPath) <> "" Then .Attachments.Add attachPath
End If
.Send
End With
SendMail = True
Exit Function
ErrHandler:
SendMail = False
End Function
VBModuleBatch(処理・集計・ロギング)
Public Sub RunBatchWithNotify()
Dim startTs As Date, endTs As Date
Dim okCount As Long, ngCount As Long
Dim failList As String
startTs = Now
On Error GoTo FatalErr
' 例: シート「Data」のA2:Aに処理対象ID、B列にステータス
Dim ws As Worksheet, lastRow As Long, r As Long
Set ws = ThisWorkbook.Worksheets("Data")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For r = 2 To lastRow
On Error GoTo ItemErr
' 処理対象の例: IDでAPIやファイル更新などを想定
Dim id As String: id = CStr(ws.Cells(r, "A").Value)
If Len(id) = 0 Then GoTo SkipItem
' 実処理(ダミー)
Call ProcessItem(id)
ws.Cells(r, "B").Value = "OK"
okCount = okCount + 1
On Error GoTo 0
GoTo NextItem
ItemErr:
ws.Cells(r, "B").Value = "NG"
ngCount = ngCount + 1
failList = failList & vbCrLf & "Row " & r & ": " & id & " — " & Err.Number & " / " & Err.Description
Err.Clear
Resume Next
SkipItem:
' 空行はスキップ
NextItem:
Next r
endTs = Now
' 成功/失敗サマリ通知
Dim subjectText As String, bodyText As String
subjectText = "[在庫バッチ] 実行結果: OK=" & okCount & " NG=" & ngCount
bodyText = "開始: " & Format(startTs, "yyyy-mm-dd HH:NN:SS") & vbCrLf & _
"終了: " & Format(endTs, "yyyy-mm-dd HH:NN:SS") & vbCrLf & _
"成功件数: " & okCount & vbCrLf & _
"失敗件数: " & ngCount & vbCrLf & _
IIf(ngCount > 0, "失敗詳細:" & vbCrLf & failList, "失敗なし")
Dim sent As Boolean
sent = SendMail(GetSettingToAddr, subjectText, bodyText, GetSettingCcAddr())
' ログ記録
LogResult startTs, endTs, okCount, ngCount, sent
Exit Sub
FatalErr:
endTs = Now
' 致命的エラーの即時通知
Call SendMail(GetSettingToAddr, "[在庫バッチ] 致命的エラー", _
"開始: " & Format(startTs, "yyyy-mm-dd HH:NN:SS") & vbCrLf & _
"終了: " & Format(endTs, "yyyy-mm-dd HH:NN:SS") & vbCrLf & _
"エラー: " & Err.Number & " / " & Err.Description)
LogResult startTs, endTs, okCount, ngCount, False
End Sub
Private Sub ProcessItem(ByVal id As String)
' 実際の更新処理をここに(例: シート更新やファイル操作)
' デモ用: ランダムでエラーを発生させる
If Rnd() < 0.1 Then Err.Raise 1001, , "Demo failure for ID=" & id
' 何らかの処理…
End Sub
Private Sub LogResult( _
ByVal startTs As Date, _
ByVal endTs As Date, _
ByVal okCount As Long, _
ByVal ngCount As Long, _
ByVal mailSent As Boolean _
)
Dim ws As Worksheet, nextRow As Long
Set ws = ThisWorkbook.Worksheets("Log")
If ws.Cells(1, 1).Value = "" Then
ws.Range("A1:E1").Value = Array("開始", "終了", "OK", "NG", "メール送信")
End If
nextRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
ws.Cells(nextRow, "A").Value = startTs
ws.Cells(nextRow, "B").Value = endTs
ws.Cells(nextRow, "C").Value = okCount
ws.Cells(nextRow, "D").Value = ngCount
ws.Cells(nextRow, "E").Value = IIf(mailSent, "Yes", "No")
End Sub
' 設定値の取得(宛先など)— 実務ではConfigシートや名前定義から読取
Private Function GetSettingToAddr() As String: GetSettingToAddr = "alerts@example.com": End Function
Private Function GetSettingCcAddr() As String: GetSettingCcAddr = "ops@example.com": End Function
VBModule1(手動実行とスケジュール)
Public Sub RunNow()
Application.ScreenUpdating = False
Application.EnableEvents = False
Randomize
Call RunBatchWithNotify
Cleanup:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
' 例: 毎朝7:30に実行(Excelが開いている前提)
Public Sub ScheduleDaily()
Application.OnTime TimeValue("07:30:00"), "RunNow", , True
End Sub
VB運用のポイントと安全策
- メール送信の安定性:
- 遅延バインディング(CreateObject)でOutlook起動有無に依存しない。
- CC/BCC/添付はオプションで柔軟に。添付は存在確認してから追加。
- 失敗時の可観測性:
- 失敗詳細を本文に列挙(行番号・ID・エラー番号/内容)。
- Logシートでサマリを時系列に保存。失敗行はB列にNGマーキング。
- 再実行のしやすさ:
- NG行のみ再実行するサブルーチンを追加すると効率的。
- 設定値をConfigシートに切り出す(宛先・スケジュール・しきい値)。
- スケジュール方法:
- Excel常駐なら OnTime。
- PC常時稼働+Excel不要なら Windowsタスクスケジューラ+VBScriptでブックを開いてマクロ実行する方式も有効。
- セキュリティ/組織ポリシー:
- Outlookのプログラムによる送信警告が出る環境あり。管理ポリシーを確認。
- メール送信のレート制限を考慮(まとめてサマリ送信にする、一定件数でバッチ化)。
拡張アイデア
- HTMLメール:
.HTMLBodyで表形式のサマリ(成功/失敗テーブル)。 - 添付ログ: CSVで失敗一覧を吐き、メールに添付。
- 通知レベル: 成功は日次サマリ、失敗は即時通知+重要度タグ付け。
- 障害ループ防止: 同一致命的エラーが連発したら1回のみ通知して停止。


