【入門編】【中級者向け】添付ファイルのファイルサイズをチェックして巨大なメールをスキップする省エネ処理 – Outlook VBA解析バイブル

スポンサーリンク
スポンサーリンク

【中級者への登竜門】Outlook VBAで「巨大な添付ファイル」をスマートに回避する——リソースを守る設計思想

こんにちは。自動化の世界へようこそ。

「マクロの記録」を使って、なんとか目的の動作を実現できた。そんな成功体験を掴んだあなた。次は「動くだけのマクロ」から「止まらない、そして賢いプログラム」へとステップアップする時が来ました。

今日扱うテーマは、実務で必ず直面する「巨大な添付ファイルの扱い」です。

「添付ファイルを自動保存するマクロを作ったけれど、時々動作が重くなる」「ディスク容量がいっぱいになってしまった」……そんな経験はありませんか?

実は、プロフェッショナルなエンジニアは、コードを書く前に「何を書かないか」を考えます。今回は、添付ファイルのサイズを事前に判定し、不要な重い処理をスキップする「省エネ(防御的)な設計」をマスターしていきましょう。ここをクリアすれば、Outlook VBAの基本はバッチリですよ。

なぜ「サイズチェック」が必要なのか?

なぜ、単に「全部保存する」ではいけないのでしょうか? それには2つの大きな理由があります。

1. リソース(計算資源)の保護

Outlook VBAにおいて、ファイルをディスクに書き出す `SaveAsFile` メソッドは、メモリとCPUを消費する「重い」処理です。もし数GBもあるような巨大な動画ファイルや、圧縮された巨大なログファイルが添付されていた場合、保存処理中にOutlookがフリーズしたり、処理時間が数分間止まってしまったりすることがあります。

2. ストレージ(容量)の保護

自動化が進むと、プログラムはあなたの代わりに「勝手に」ファイルを保存し続けます。サイズ制限を設けていないと、気づかないうちにサーバーやPCのディスク容量を食いつぶし、システム全体のクラッシュを招くリスクがあります。

「重い処理をする前に、まず中身をチラ見する」。これが、賢いエンジニアの鉄則です。

実装の鍵:`Attachment.Size` プロパティ

Outlookの `Attachment` オブジェクトには、`.Size` というプロパティが用意されています。この値は、「バイト(Bytes)」単位で返されます。

ここでのポイントは、「ファイルの実体を保存する前に、メタデータ(属性情報)だけを読み取って判定する」という点です。メタデータの読み取りは一瞬ですが、ファイルの保存は時間がかかります。この「コストの差」を利用するのが、今回の設計の肝です。

実践:スマートな添付ファイル保存コード

それでは、実際に使えるコードを見てみましょう。
このコードは、「指定したサイズ(MB)を超えるファイルは保存せずにスキップする」というロジックを持っています。

Option Explicit

''' <summary>
''' 選択中のメールから添付ファイルを保存する。
''' ただし、指定サイズを超える巨大なファイルはスキップする。
''' </summary>
Sub SaveAttachmentsWithSizeLimit()
    ' --- 設定エリア ---
    Const MAX_SIZE_MB As Double = 10# ' 【設定】スキップする上限サイズ (MB)
    Const SAVE_DIR As String = "C:\Users\YourName\Desktop\SavedAttachments\" ' 【設定】保存先フォルダ
    ' ------------------

    Dim objMail As Outlook.MailItem
    Dim objAttachment As Outlook.Attachment
    Dim maxSizeInBytes As Double
    Dim savePath As String
    Dim skippedCount As Integer
    Dim savedCount As Integer

    ' 1. 選択中のアイテムがメールかどうかをチェック
    If Application.ActiveExplorer.Selection.Count = 0 Then
        MsgBox "メールを選択してください。", vbExclamation
        Exit Sub
    End If

    If TypeName(Application.ActiveExplorer.Selection.Item(1)) <> "MailItem" Then
        MsgBox "メールアイテムを選択してください。", vbExclamation
        Exit Sub
    End If

    Set objMail = Application.ActiveExplorer.Selection.Item(1)
    
    ' 2. バイト単位の閾値を計算 (MB -> Bytes)
    ' 1MB = 1024 * 1024 Bytes
    maxSizeInBytes = MAX_SIZE_MB * 1024 * 1024
    
    skippedCount = 0
    savedCount = 0

    ' 3. 添付ファイルをループ処理
    For Each objAttachment In objMail.Attachments
        
        ' 【ここが核心】サイズを先にチェック!
        If objAttachment.Size > maxSizeInBytes Then
            ' サイズオーバーの場合は保存せずにカウントアップして次へ
            Debug.Print "SKIPPED: " & objAttachment.FileName & " (" & Round(objAttachment.Size / 1024 / 1024, 2) & " MB)"
            skippedCount = skippedCount + 1
        Else
            ' サイズが範囲内なら保存処理を実行
            ' 保存先パスの組み立て(ファイル名に重複がある場合は上書きされるので注意)
            savePath = SAVE_DIR & objAttachment.FileName
            
            On Error Resume Next ' ファイル書き込みエラー対策
            objAttachment.SaveAsFile savePath
            
            If Err.Number = 0 Then
                savedCount = savedCount + 1
            Else
                MsgBox "保存失敗: " & objAttachment.FileName & vbCrLf & Err.Description, vbCritical
            End If
            On Error GoTo 0
        End If
        
    Next objAttachment

    ' 4. 結果の報告
    MsgBox "処理が完了しました。" & vbCrLf & _
           "保存成功: " & savedCount & " 件" & vbCrLf & _
           "スキップ: " & skippedCount & " 件 (サイズ超過)", vbInformation

End Sub

コードの解説:エンジニアの視点

このコードには、単なる動作以上の「意図」が込められています。

① 単位変換の計算式

`maxSizeInBytes = MAX_SIZE_MB * 1024 * 1024`
プログラミングの世界では、1KBは1000ではなく1024です。このように、「人間が理解しやすい単位(MB)」を「コンピュータが扱う単位(Bytes)」に変換する工程を挟むことで、設定のしやすさと正確性を両立させています。

② ガード節(Early Exit)的な考え方

`If objAttachment.Size > maxSizeInBytes Then … Else …`
この構造は、条件に合わないものを「先に弾く」という考え方に基づいています。条件を満たさないものに対して、重い処理(`SaveAsFile`)を一切実行させない。これがパフォーマンスを最大化するコツです。

③ エラーハンドリングの重要性

`On Error Resume Next` を使っていますが、これは決して「エラーを無視していい」という意味ではありません。ファイルが使用中だったり、保存先フォルダが存在しなかったりする場合に、「マクロ全体がクラッシュして止まるのを防ぐ」ために、局所的にエラーを制御しています。

陥りやすいエラーと対策

中級者への道を進む中で、以下の落とし穴に注意してください。

1. 保存先フォルダが存在しない
`SAVE_DIR` で指定したパスが実際に存在しない場合、`SaveAsFile` はエラーになります。実務用のコードでは、`FileSystemObject` を使って「フォルダがなければ作成する」という処理を追加すると、さらに堅牢(ロバスト)になります。
2. ファイル名の重複
同じ名前のファイルが添付されていた場合、後のファイルが前のファイルを上書きしてしまいます。これを防ぐには、ファイル名の末尾に `Format(Now, “yyyymmddhhmmss”)` のようなタイムスタンプを付与する工夫が必要です。
3. データ型の選択
添付ファイルのサイズは非常に大きくなる可能性があります。`Integer` 型(最大約3.2万)ではなく、必ず `Long` 型や `Double` 型を使用して、大きな数値(バイト数)を扱えるようにしておきましょう。

まとめ:一歩先の自動化へ

「動けばいい」という段階から、「どんな状況でも安全に、効率よく動く」という段階へ。
今回学んだ「事前判定によるリソース保護」は、VBAに限らず、あらゆるプログラミング言語に共通する極めて重要な設計思想です。

次にコードを書くときは、ぜひ自分に問いかけてみてください。
「もし、ここに巨大なデータが流れてきたら、このプログラムはどう振る舞うだろうか?」

この視点を持つことが、あなたを真のエンジニアへと導いてくれます。
応援していますよ!

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