【入門編】【中級者向け】Excelのスケジュール表から「送信予約日時」を読み取り、DeferredDeliveryTimeを一括設定するツール – Outlook VBA解析バイブル

スポンサーリンク

こんにちは!エンジニアリングの世界へようこそ。
今日は、日々の定型業務で多くの人が頭を悩ませる「メールの送信予約」を、ExcelとOutlook VBAの連携で完全に自動化するテクニックを伝授します。

「毎週月曜日の朝8時に、この進捗報告メールを出したいけれど、うっかり忘れてしまいそう……」
「深夜に作業が終わったけれど、クライアントへのメールは翌朝の適切な時間に飛ばしたい……」

そんな悩みを一発で解決するのが、Outlookの裏ワザ的プロパティ `DeferredDeliveryTime` です。
ここをクリアすれば、あなたのOutlook VBAのスキルは一気に中級者の領域へステップアップします。さあ、一緒に極めていきましょう!

—

1. なぜ「送信予約(DeferredDeliveryTime)」なのか?

多くの人が「メールを自動送信する」というと、Windowsのタスクスケジューラや、VBAのタイマー処理(`Application.OnTime`)を思い浮かべます。しかし、それらは「PCが起動しており、Outlookがアクティブに稼働していること」が絶対条件という致命的な弱点があります。

一方、今回使う `DeferredDeliveryTime` プロパティは、メールをOutlookの「送信トレイ(Outbox)」に「指定した日時まで保持させる」という仕組みです。

  • 仕組み: VBAでメールを作成し、送信日時を設定して「送信(Send)」ボタンを押す(プログラムから実行する)と、メールは即座に「送信トレイ」に入ります。
  • 最大のメリット: あとはOutlookが勝手にその時間までメールを抱えておいてくれるため、指定した時間になったらPCの電源が入っていなくても(※Exchange環境等やOutlookの仕様に依存しますが基本のローカル保持として)、バックグラウンドで安全に発射されます。

この「下書きや送信トレイに予約状態で溜め込む」というアプローチこそ、実務で最も堅牢(ロバスト)な自動化手法なのです。

—

2. 全体像とアーキテクチャ

今回のツールは、次のようなフローで動作します。

[Excelのスケジュール表]
┣ 宛先 (To)
┣ 件名 (Subject)
┣ 本文 (Body)
ジ 予約日時 (DeferredDeliveryTime)
↓
[VBAエンジンがデータを一括読み込み]
↓
[Outlookの MailItem オブジェクトを生成]
↓
[DeferredDeliveryTime に日時をバインド]
↓
[送信トレイへ一斉格納(予約完了!)]

Excel側には、例えば以下のようなテーブルを用意しておきます。

| 宛先 (A列) | 件名 (B列) | 本文 (C列) | 送信予約日時 (D列) |
| :— | :— | :— | :— |
| test1@example.com | 進捗報告(第1週) | 今週の進捗をお送りします。 | 202X/12/01 09:00 |
| test2@example.com | 進捗報告(第2週) | 来週の予定です。 | 202X/12/08 09:00 |

—

3. 実装コード:ExcelからOutlookを完全制御する

それでは、実際にExcelのVBAエディタ(VBE)に記述するコードを公開します。
今回はExcel側の標準モジュールに記述し、裏でOutlookを操作する「CtoA(Client to Application)パターン」をとります。

事前準備(参照設定の推奨)

VBEのメニュー [ツール] > [参照設定] から 「Microsoft Outlook 16.0 Object Library」(数字はバージョンにより異なります)にチェックを入れておくと、コードの補完が効くようになり開発が爆発的に楽になります。

Sub CreateScheduledEmailsFromExcel()
‘————————————————–
‘ 宣言セクション
‘————————————————–
Dim olApp As Object ‘ 実行時バインディングでOutlookを安全に起動
Dim olMail As Object ‘ MailItemオブジェクト
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long

‘ 変数定義(Excelデータ受信用)
Dim mailTo As String
Dim mailSubject As String
Dim mailBody As String
Dim sendDate As Variant

‘————————————————–
‘ 1. Excelデータの特定と取得準備
‘————————————————–
Set ws = ThisWorkbook.Sheets(“Sheet1”) ‘ 実際のシート名に合わせて変更してください

‘ データが入力されている最終行を取得(A列基準)
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row

If lastRow < 2 Then MsgBox "処理対象のデータが見つかりません。", vbExclamation, "中断" Exit Sub End If '-------------------------------------------------- ' 2. Outlookアプリケーションのインスタンス生成 '-------------------------------------------------- On Error Resume Next Set olApp = GetObject(, "Outlook.Application") If olApp Is Nothing Then Set olApp = CreateObject("Outlook.Application") End If On Error GoTo 0 If olApp Is Nothing Then MsgBox "Outlookを起動できませんでした。強制終了します。", vbCritical Exit Sub End If '-------------------------------------------------- ' 3. ループ処理によるメールの一括生成&予約設定 '-------------------------------------------------- ' 2行目から最終行までループ For i = 2 To lastRow ' セルから値を変数に格納 mailTo = ws.Cells(i, 1).Value mailSubject = ws.Cells(i, 2).Value mailBody = ws.Cells(i, 3).Value sendDate = ws.Cells(i, 4).Value ' 宛先が空でない場合のみ処理を実行 If mailTo <> “” Then
‘ MailItemの新規作成(olMailItem = 0)
Set olMail = olApp.CreateItem(0)

With olMail
.To = mailTo
.Subject = mailSubject
.Body = mailBody

‘ 【最重要】送信予約日時の設定
‘ Excelから取得した値が「正しい日時データ」であるかを判定して代入
If IsDate(sendDate) Then
If CDate(sendDate) > Now Then
.DeferredDeliveryTime = CDate(sendDate)
Else
‘ 過去の日時の場合は警告を出してスキップ、または即時送信にしないための安全策
Debug.Print i & “行目の予約日時は過去のため、スキップしました。”
GoTo NextLoop
End If
End If

‘ ここがポイント!
‘ Sendメソッドを実行すると、DeferredDeliveryTimeのおかげで
‘ すぐには飛ばず、「送信トレイ」に予約保持されます。
.Send

End With

‘ オブジェクトのメモリ解放(メモリリーク防止のプロの技)
Set olMail = Nothing
End If

NextLoop:
Next i

‘————————————————–
‘ 4. 終了処理
‘————————————————–
Set olApp = Nothing
MsgBox “すべての予約メールの作成と送信トレイへの格納が完了しました!”, vbInformation, “完了”

End Sub

—

4. 現場で絶対にハマる「3大エラー」と回避の極意

プログラミング初学者がこのコードを実務で動かす際、高い確率で直面する壁と、そのスマートな回避方法を伝授します。

① 型のミスマッチ(Type Mismatch)エラー

  • 現象: `CDate(sendDate)` の部分で突然エラーが起きて止まる。
  • 原因: Excelのセルに「文字(文字列型)」として日時が入っていたり、セルが空白のまま判定に入ってしまっている。
  • 解決策: コード内に入れている `IsDate(sendDate)` による型ガードが命綱です。Excel側でもセルの書式設定を必ず「日付」や「ユーザー定義 (yyyy/mm/dd hh:mm)」に固定する運用を徹底しましょう。

② 予約時間が「過去」になっていて即時送信されてしまう

  • 現象: テストのつもりで過去の時間を設定したら、メールが即座に発射されてしまい冷や汗をかいた。
  • 原因: `DeferredDeliveryTime` に現在時刻より前の値を渡すと、Outlookは「予約なし(即時送信)」とみなして容赦なくメールを送り出します。
  • 解決策: コード内の `If CDate(sendDate) > Now Then` というガード節がこれを防ぎます。実務では「未来の時間しかセットさせない」というバリデーションが身を守ります。

③ セキュリティ警告・アドインの干渉

  • 現象: `OlMail.Send` を実行した瞬間に、Outlookから「プログラムがメールを送信しようとしています。許可しますか?」というウザいポップアップが出る。
  • 原因: ウイルス対策ソフトやOutlook自体のセキュリティポリシーによる制限です。
  • 解決策: 社内PCのポリシーで制御されている場合は管理者に従う必要がありますが、個人の環境であれば、Outlookの「ファイル > オプション > 信頼センター > 信頼センターの設定 > プログラムによるアクセス」から設定を変更するか、信頼できるアンチウイルスソフトを最新に保つことで回避できます。

—

5. 先進的エンジニアへのステップアップ(まとめ)

お疲れ様でした!
ここまで理解できれば、単なる「マクロの記録の貼り付け」から脱却し、「外部アプリケーション(ExcelとOutlook)のオブジェクトを自在に操り、時間をコントロールする自動化エンジニア」の仲間入りです。

  • Excelからデータを安全に吸い上げ、
  • Outlookのインスタンスをスマートに制御し、
  • `DeferredDeliveryTime` という強力なプロパティで未来の送信を予約する。

この技術をベースに、CCの動的制御や、添付ファイルの自動付与などを組み合わせれば、あなたの業務効率は10倍以上に跳ね上がります。

ここをクリアできたら、Outlook VBAの基本はもうバッチリです!ぜひ自分の業務データでテストして、その感動を味わってみてくださいね。次回の応用編もお楽しみに!

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