【脱・マクロ記録】Outlook VBAを極める:正規表現で添付ファイルを「狙い撃ち」して保存する技術
こんにちは。業務自動化の世界へようこそ。
「マクロの記録」ボタンを押して、なんとか自動化の第一歩を踏み出したあなた。素晴らしい一歩です。でも、実際に動かしてみると、こんな壁にぶつかりませんでしたか?
*「メールに付いているロゴ画像や署名のアイコンまで、全部保存されてしまう……」*
*「ファイル名が『請求書_20231001.pdf』だったり『20231001_見積書.pdf』だったりして、条件分岐が複雑すぎてコードがスパゲッティ状態だ……」*
これらは、あなたが「記録」から「設計」のフェーズへ進むための、いわば卒業試験のようなものです。
今日は、そんな悩みを一撃で解決する「正規表現(Regular Expression)」という強力な武器を、Outlook VBAの中でどう使いこなすか。その極意を伝授します。ここをクリアすれば、あなたの自動化スキルは「単なる作業の代行」から「知的なエージェントの構築」へと進化しますよ。
なぜ「単純な比較」では足りないのか?
通常、ファイル名を判定するとき、多くの人は `If fileName = “請求書.pdf” Then` のような書き方や、`InStr` 関数を使った部分一致を試みます。
しかし、実務のファイル名は、エンジニアの思い通りには動いてくれません。
- `20231025_請求書_株式会社A.pdf`
- `【重要】見積書(案).xlsx`
- `invoice_12345.pdf`
これらすべてに対応しようとすると、`If` 文が延々と続く、読みづらくメンテナンス性の低いコードになってしまいます。
ここで登場するのが正規表現です。正規表現とは、文字列の「パターン」を記述する特殊な言語のこと。これを使えば、「『請求書』か『見積書』という言葉が、ファイル名のどこかに含まれていればOK」というルールを、わずか一行のパターンで表現できるのです。
武器の準備:VBScript.RegExp とは
VBAで正規表現を使うには、Windowsが標準で持っている `VBScript.RegExp` というオブジェクトを利用します。
このオブジェクトには、主に3つの重要なプロパティがあります。
1. Pattern: 「どんな文字列を探すか」というルール(例:`請求書|見積書`)
2. Global: 文書全体を探すかどうか(今回は単一の判定なので `False` でOK)
3. IgnoreCase: 大文字・小文字を区別するかどうか(英語が含まれる場合に重要)
これらを使いこなすことで、ファイル名という「不規則なデータ」を、正確に「狙い撃ち」できるようになります。
実践:添付ファイル・スナイパーの実装
それでは、実際に動くコードを見てみましょう。
このコードは、受信トレイのメールをスキャンし、ファイル名に「請求書」または「見積書」が含まれる添付ファイルだけを、指定したフォルダへ保存するものです。
Option Explicit
''' <summary>
''' 特定のキーワードを含む添付ファイルのみを抽出して保存する
''' </summary>
Sub SaveSpecificAttachments()
' --- 設定エリア ---
Dim savePath As String
Dim patternString As String
' 保存先フォルダ(末尾に必ず \ をつけること)
savePath = "C:\Users\YourName\Documents\SavedAttachments\"
' 正規表現パターン: 「請求書」 または 「見積書」 を含む
' | は「または(OR)」を意味する記号です
patternString = "請求書|見積書"
' ------------------
Dim outlookApp As Outlook.Application
Dim ns As Outlook.NameSpace
Dim inbox As Outlook.Folder
Dim mailItem As Object
Dim attachment As Outlook.Attachment
' 正規表現オブジェクト(Late Binding: 参照設定なしで動くように実装)
Dim regExp As Object
Set regExp = CreateObject("VBScript.RegExp")
With regExp
.Pattern = patternString
.IgnoreCase = True ' 大文字小文字を区別しない
.Global = False ' 最初に見つかった時点で判定終了
End With
' Outlookオブジェクトのセットアップ
Set outlookApp = New Outlook.Application
Set ns = outlookApp.GetNamespace("MAPI")
Set inbox = ns.GetDefaultFolder(olFolderInbox)
' フォルダが存在するか、書き込み可能かのチェック(実務では必須!)
If Dir(savePath, vbDirectory) = "" Then
MsgBox "保存先フォルダが見つかりません: " & savePath, vbCritical
Exit Sub
End If
Debug.Print "--- 処理開始: " & Now & " ---"
' 受信トレイのアイテムをループ
' ※大量のメールがある場合は、処理時間を考慮して範囲を絞るのがプロの技
For Each mailItem In inbox.Items
' メールアイテム(MailItem)である場合のみ処理
If TypeOf mailItem Is Outlook.MailItem Then
' 添付ファイルのループ
For Each attachment In mailItem.Attachments
' 【ここが心臓部】正規表現でファイル名を判定
If regExp.Test(attachment.FileName) Then
' 条件に一致した場合のみ保存
Dim fullPath As String
fullPath = savePath & attachment.FileName
' 同名ファイルによるエラーを防ぐための処理
If Dir(fullPath) <> "" Then
fullPath = savePath & Format(Now, "yyyymmddhhmmss_") & attachment.FileName
End If
attachment.SaveAsFile fullPath
Debug.Print "保存成功: " & attachment.FileName
Else
' 条件に合わないものは無視
Debug.Print "スキップ: " & attachment.FileName
End If
Next attachment
End If
Next mailItem
Debug.Print "--- 処理完了 ---"
MsgBox "添付ファイルの抽出処理が完了しました。", vbInformation
' オブジェクトの解放(メモリリークを防ぐための大切な作法)
Set regExp = Nothing
Set ns = Nothing
Set outlookApp = Nothing
End Sub
コードの解剖図:プロの視点
このコードには、単なる「動くコード」以上の、実務で耐えうるための工夫がいくつか散りばめられています。
1. Late Binding(遅延結合)の採用
`CreateObject(“VBScript.RegExp”)` を使っていますね。これは「参照設定」をあらかじめ行わなくても動く書き方です。他の人にこのツールを配る際、相手の環境で「参照不可エラー」が出るのを防ぐための、配慮の行き届いた設計です。
2. `regExp.Test` メソッドの威力
`If regExp.Test(attachment.FileName) Then`
この一行が、これまでの複雑な `If` 文をすべて飲み込みます。`Test` メソッドは、パターンに一致すれば `True` を、しなければ `False` を返す非常に高速な判定メソッドです。
3. ファイル名の衝突回避
実務では、同じ名前のファイル(例:`請求書.pdf`)が何度も届きます。そのまま `SaveAsFile` すると、上書きされるかエラーになります。
ここでは、既にファイルが存在する場合に、ファイル名の先頭にタイムスタンプ(`yyyymmddhhmmss_`)を付与する処理を入れています。これこそが、「壊れないツール」を作るための思考です。
陥りやすい罠:設計者が気をつけるべき3つのポイント
ここをクリアすれば、あなたも立派な自動化エンジニアです。
1. オブジェクトのライフサイクルを意識せよ
VBAは強力ですが、メモリ管理はあなたの責任です。使い終わった `regExp` や `outlookApp` は、必ず `Set … = Nothing` で解放する癖をつけましょう。大規模なループ処理でこれを怠ると、Outlookが突然落ちる原因になります。
2. 正規表現のパターンは「欲張りすぎない」
パターンを `.*`(何でもあり)のように書きすぎると、意図しないファイルまで拾ってしまいます。「何を含むか」だけでなく、「何を含まないか」を意識することも重要です。
3. エラーハンドリングを忘れない
ネットワークドライブに保存しようとして接続が切れたとき、あるいはファイルが他のプログラムで開かれているとき……。実務では、コードが止まることは「想定内」です。`On Error GoTo …` を使って、エラーが起きてもログを残して次に進む設計を心がけましょう。
おわりに
いかがでしたか?
正規表現をマスターすることは、単にコードを短くすることではありません。「不規則な現実世界を、論理的なルールでコントロールする力」を手に入れることなのです。
最初はパターンを考えるのが難しく感じるかもしれません。でも、一歩ずつ、試行錯誤しながら進んでいけば大丈夫。もし迷ったら、またここに戻ってきてください。
さあ、次はどんな業務を、あなたの魔法(コード)で自動化しましょうか?応援していますよ!
