Excel VBA 逆引き集 | 実務テンプレ完全版(超再利用部品) – 自動配信ツール(メール)

Excel VBA
スポンサーリンク

ねらい:Excelの一覧から「宛先・件名・本文・添付」を自動でメール配信する“型”を作る

毎回同じようなメールを、宛先や本文の一部だけ変えて送る――これを手作業でやるのは時間のムダです。
VBA なら「一覧をなめる → Outlook メールを作る → 差し込み → 送信(または下書き保存)」を“ひな形化”できます。

ここでは、プログラミング初心者でも貼って動くように、

  • シート設計(誰に、何を)
  • Outlook 宛のメール作成テンプレ
  • 一括配信(送信/下書き)
  • よくあるパターン(請求書、レポート、リマインドなど)

を、かみ砕いて説明します。


準備:シート設計と Outlook 連携の考え方

シート設計(最低限これだけは用意する)

まずは、次のようなシートを 1 枚用意します(名前は「MailList」とします)。

A列:SendFlag(送信対象か Y/N)
B列:To(宛先メールアドレス)
C列:Cc(CC、空でも可)
D列:Subject(件名)
E列:BodyTemplate(本文テンプレート)
F列:AttachmentPath(添付ファイルのフルパス、空でも可)
G列:Name(差し込み用の名前)
H列:Extra1(差し込み用の追加項目)

本文テンプレート(E列)は、こんな風にプレースホルダを含めておきます。

{Name} 様

いつもお世話になっております。
{Extra1} の件につきまして、ご連絡申し上げます。

よろしくお願いいたします。

あとで VBA 側で {Name}{Extra1} を置き換えるイメージです。

Outlook を使う前提(Excel からメールを飛ばす仕組み)

Excel VBA でメール自動送信する時は、ほぼ「Outlook の自動操作」です。

  • Outlook がインストールされている
  • (できれば)Outlook が起動している

ことが前提になります。

初心者向けには「早送りはせず、とりあえず下書きに保存して確認してから送る」運用が安全です。
あとで「自動送信モード」に切り替えるテンプレも用意します。


共通基盤:Outlook メール作成の基本テンプレ

Outlook メールを 1 通作る最小コード

まずは最も小さい“1通を作って送る”テンプレです。

' ModMail_Base.bas
Option Explicit

Public Function GetOutlookApp() As Object
    On Error Resume Next
    Set GetOutlookApp = GetObject(, "Outlook.Application")
    If GetOutlookApp Is Nothing Then
        Set GetOutlookApp = CreateObject("Outlook.Application")
    End If
End Function

Public Sub SendTestMail()
    Dim olApp As Object
    Dim olMail As Object
    
    Set olApp = GetOutlookApp()
    Set olMail = olApp.CreateItem(0) ' 0 = olMailItem
    
    With olMail
        .To = "test@example.com"
        .CC = ""
        .Subject = "テストメール"
        .Body = "これはテストメールです。" & vbCrLf & "Excel VBA から送信しています。"
        ' .Display ' 画面に表示するだけ(確認用)
        .Send    ' いきなり送信
    End With
End Sub
VB

ここで重要なポイントは 2 つです。

1つ目:GetOutlookApp で、既に起動している Outlook があればそれを使い、なければ起動するという“お作法”にしていること。

2つ目:.Display.Send を切り替えることで、「目で確認してから送る/自動で送る」を切り替えられること。
最初は必ず .Display で確認するのをおすすめします。


差し込み機能:本文テンプレートの {Name} や {Extra1} を置き換える

プレースホルダ置換の小さな関数

' ModMail_Template.bas
Option Explicit

Public Function ApplyTemplate(ByVal template As String, ByVal key As String, ByVal value As String) As String
    ApplyTemplate = Replace(template, "{" & key & "}", value)
End Function

Public Function BuildBody(ByVal template As String, ByVal name As String, ByVal extra1 As String) As String
    Dim body As String
    body = template
    body = ApplyTemplate(body, "Name", name)
    body = ApplyTemplate(body, "Extra1", extra1)
    BuildBody = body
End Function
VB

これで、

  • テンプレ:"{Name} 様 … {Extra1} の件 …"
  • Name: "山田"
  • Extra1: "売上レポート"

という入力から、きちんと差し込まれた本文が作れます。

本番では、差し込む項目が増えたら BuildBody の中を増やすだけで対応できます。


一括配信ロジック:一覧をループして Outlook メールを量産する

シートの 1 行 = 1 通のメールとして処理する

' ModMail_Bulk.bas
Option Explicit

Public Sub BulkMail_FromSheet(Optional ByVal sendNow As Boolean = False)
    Dim ws As Worksheet
    Set ws = Worksheets("MailList")
    
    Dim a As Variant
    a = ReadRegion(ws)   ' A1 からの表全体
    
    Dim olApp As Object
    Dim olMail As Object
    Set olApp = GetOutlookApp()
    
    Dim r As Long
    For r = 2 To UBound(a, 1) ' 2行目から最終行まで
        Dim flag As String
        flag = UCase$(Trim$(CStr(a(r, 1)))) ' SendFlag
        
        If flag = "Y" Then
            Dim mailTo As String
            Dim mailCc As String
            Dim subj As String
            Dim tmpl As String
            Dim attachPath As String
            Dim name As String
            Dim extra1 As String
            
            mailTo = Trim$(CStr(a(r, 2)))
            mailCc = Trim$(CStr(a(r, 3)))
            subj = CStr(a(r, 4))
            tmpl = CStr(a(r, 5))
            attachPath = Trim$(CStr(a(r, 6)))
            name = CStr(a(r, 7))
            extra1 = CStr(a(r, 8))
            
            Dim body As String
            body = BuildBody(tmpl, name, extra1)
            
            If Len(mailTo) = 0 Then
                ' 宛先がない行は飛ばす(ログを取りたい場合はここで別処理)
                GoTo NextRow
            End If
            
            Set olMail = olApp.CreateItem(0)
            With olMail
                .To = mailTo
                .CC = mailCc
                .Subject = subj
                .Body = body
                
                If Len(attachPath) > 0 Then
                    If Dir(attachPath) <> "" Then
                        .Attachments.Add attachPath
                    Else
                        ' 添付ファイルが見つからない場合も本当はログを残すと良い
                        .Body = body & vbCrLf & vbCrLf & "[※ 添付ファイルが見つかりませんでした: " & attachPath & "]"
                    End If
                End If
                
                If sendNow Then
                    .Send       ' 自動送信モード
                Else
                    .Display    ' 下書きとして開くだけ
                End If
            End With
        End If
        
NextRow:
    Next r
    
    MsgBox "メール自動配信処理が完了しました。", vbInformation
End Sub
VB

ここでの“肝”を整理します。

SendFlag 列が Y の行だけ処理します。
これにより、「この人だけ今回は送らない」という制御が簡単にできます。

sendNow 引数で「自動送信/表示のみ」を切り替えています。
最初は BulkMail_FromSheet False のように呼び出し、すべてのメールウィンドウが表示された状態で中身を確認してから、
OK になったら True にして“ガチ自動送信”に切り替えるのが安全です。

添付ファイルのパスが存在しない場合は、その旨を本文に追記しています。
実務では「ログシート」にも“添付ファイル未検出”を記録しておくと、後から原因の特定が楽になります。


例題:レポートを個別に添付して自動配信する

想定シナリオ

  • 各顧客ごとに作成されたレポート(PDF)がフォルダにある
  • ファイル名は レポート_顧客ID.pdf のような規則でついている
  • MailList シートには、顧客ID とメールアドレスと名前が入っている

この場合、添付ファイルパス列(F列)を「自動で埋めてから送る」テンプレにできます。

添付パスを自動で作る例

' ModMail_AttachPrep.bas
Option Explicit

Public Sub PrepareAttachments()
    Dim ws As Worksheet
    Set ws = Worksheets("MailList")
    
    Dim a As Variant
    a = ReadRegion(ws)
    
    Dim baseFolder As String
    baseFolder = ThisWorkbook.Path & "\Reports" ' レポートが入っているフォルダ
    
    Dim r As Long
    For r = 2 To UBound(a, 1)
        Dim custId As String
        custId = Trim$(CStr(a(r, 9))) ' 例:I列に顧客IDがあると仮定
        
        If Len(custId) > 0 Then
            Dim path As String
            path = baseFolder & "\Report_" & custId & ".pdf"
            a(r, 6) = path ' 添付パス列に書き込み(F列=6)
        End If
    Next
    
    WriteBlock ws, a, "A1"
    FormatBlock ws, "A1"
    
    MsgBox "添付パスの準備が完了しました。", vbInformation
End Sub
VB

この後に BulkMail_FromSheet False を実行すると、各行に対応する PDF を添付したメールが Outlook 上に開きます。
問題なければ BulkMail_FromSheet True に切り替えて本番運用にできます。


重要ポイントの深掘り:安全・確実に自動配信するための“クセづけ”

いきなり .Send しない(まずは Display で人間が最終確認)

メール自動化で一番やりがちな事故は、「宛先間違いの一斉送信」です。
これを避けるために、

  • 開発・テスト段階は必ず .Display にして目で確認
  • 宛先を全て自分のテストアドレスにして動作確認
  • その後、本番アドレスに差し替える

というステップを「必ず踏む」ことをおすすめします。

BulkMail_FromSheet を呼ぶ Sub を 2 本用意して、

Sub Mail_Check()
    BulkMail_FromSheet False   ' 表示のみ
End Sub

Sub Mail_Send()
    BulkMail_FromSheet True    ' 自動送信
End Sub
VB

のように分けておくと、間違いが起きにくくなります。

シートの設計を“仕様書化”しておく

MailList シートの列構成(列の意味)は、必ずコメントや別シートで仕様として書き残しておきましょう。

  • A=SendFlag (Y/N)
  • B=To
  • C=Cc
  • D=Subject
  • E=BodyTemplate
  • F=AttachmentPath
  • G=Name
  • H=Extra1
  • I=CustomerID

など。

後から列を追加したり名前を変えたりする時に、VBA 側の「何列目を読んでいるか」との対応が分からなくなるのを防げます。

列番号でなく「列名」で取るように拡張することも可能ですが、
初心者向けにはまず「列は固定」という前提で運用を固めてしまう方が楽です。

ログを残すと“後で助かる”

本格運用になってくると、

  • 何行目の誰に
  • いつ送ったか/送らなかったか
  • 添付ファイルは見つかったか

といったログが欲しくなります。

簡単な方法は、MailList シートの右側に「SentDate」「Error」といった列を追加して、
送信処理の中で、

ws.Cells(r, 10).Value = Now          ' SentDate
ws.Cells(r, 11).Value = "OK"         ' Error列に結果
VB

などと書き込むことです。
後から「送れた/送れていない」の確認が一瞬でできるようになります。

セルを逐次触らず、配列でまとめて処理するクセをつける

今回のコードも、基本的には

  • ReadRegion → 配列処理 → WriteBlock

という流れにしています。
セルを一つずつ読み書きするコードに慣れてしまうと、行数が増えたときに一気に重くなり、“固まる Excel”ができあがります。

自動配信ツールは、数百件〜数千件のメールを対象にすることもあるので、
最初から「配列中心の設計」にしておくと後々ラクです。


まとめ:シートで“誰に何を送るか”を書き、VBA で「差し込み・添付・送信」を自動化する

自動配信ツール(メール)は、
「シートでシナリオを定義 → VBA で Outlook を操作 → Display/Send を切り替える」だけで、かなり実務的なレベルに到達します。

  • SendFlag と To/Cc で“誰に送るか”
  • Subject/BodyTemplate と差し込みで“何を送るか”
  • AttachmentPath で“何を添付するか”

をシートに書かせて、VBA 側は“機械的に流すだけ”にするのが、壊れにくくて強い設計です。

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