ネットワークの向こう側にある「不完全なファイル」を許さない。VBAで実装するレジリエント(回復力のある)な一括エクスポート術
こんにちは。今日もコードと向き合っているあなた、素晴らしいですね。
「マクロの記録」を使って、自動化の第一歩を踏み出した。それはエンジニアとして非常に正しいステップです。でも、あなたが現場で「実戦」に投入しようとしたとき、ある壁にぶつかるはずです。
それは、「プログラムは完璧なのに、ネットワークが原因で失敗する」という問題です。
例えば、VPN越しに共有サーバーへPDFを一括保存するマクロを書いたとしましょう。通信が不安定なとき、保存の途中で一瞬だけパケットが途切れることがあります。するとどうなるか? サーバーには、「中身が空っぽのPDF」や「開こうとするとエラーが出る破損したPDF」がポツンと残されてしまうのです。
これでは、自動化どころか、後で人間が「どれが正しいファイルか」を確認する手間が増えてしまいますよね。
今日は、そんな「現場の理不尽」を技術でねじ伏せる、トランザクション(一連の処理)の整合性を守るためのレジリエント(回復力のある)な制御手法を伝授します。ここをマスターすれば、あなたの作るツールは「動くだけのツール」から「プロが信頼するシステム」へと進化します。
1. なぜ「ただの保存」ではダメなのか?(概念の理解)
まず、私たちが戦っている相手を理解しましょう。
通常の「マクロの記録」で作ったコードは、以下のような考え方です。
1. ファイルを開く
2. PDFとして保存する
3. 次のファイルへ行く
これ、実は非常に危ういんです。「2」の途中で通信が切れた場合、プログラムは「エラー」として止まるか、あるいは「不完全なファイルを作ったまま、そのまま次の処理に進んでしまう」からです。
プロの設計では、これを「原子性(Atomicity)」という考え方で制御します。
「保存が完全に成功したか、さもなくば、最初から何もなかったことにする(ロールバック)」という考え方です。
今回実装する「レジリエント制御」のフロー図
[開始]
│
├─ ファイルを一つ選択
│ │
│ ├─ [Try: 実行フェーズ]
│ │ └─ PDFとしてエクスポートを試みる
│ │
│ └─ [Catch: エラー検知フェーズ]
│ │
│ ├─ もし通信エラー等が発生したら...
│ │ └─ [Rollback: 回復フェーズ]
│ │ └─ 中途半端に生成されたゴミファイルを即座に削除!
│ │
│ └─ 成功したら、次のファイルへ
│
[完了]
2. 実践:レジリエントPDFエクスポート・マクロ
それでは、実際に使えるコードを見ていきましょう。
このコードでは、`FileSystemObject`(ファイル操作のプロ)と、VBAの強力なエラーハンドリング機能 `On Error GoTo` を組み合わせています。
Option Explicit
''' <summary>
''' ネットワーク越しでも安全にPDFを一括エクスポートする
''' </summary>
Sub ResilientBatchPDFExport()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
' --- 設定エリア ---
Dim sourceFolder As String: sourceFolder = "C:\Your\Source\Path\" ' 元のPPTXがあるフォルダ
Dim targetFolder As String: targetFolder = "\\NetworkServer\Shared\PDF_Export\" ' 保存先(ネットワーク)
' ------------------
Dim pptFile As Object
Dim pptApp As PowerPoint.Application
Dim pres As PowerPoint.Presentation
Dim targetPath As String
Dim fileNameOnly As String
Set pptApp = PowerPoint.Application
' フォルダ内のファイルを取得するループ(簡易版)
' 本来はDir関数などでループさせますが、ここでは概念を明確にするため構造を示します
Dim targetFile As String
targetFile = Dir(sourceFolder & "*.pptx")
Do While targetFile <> ""
' ファイル名(拡張子なし)を取得
fileNameOnly = CreateObject("Scripting.FileSystemObject").GetBaseName(targetFile)
targetPath = targetFolder & fileNameOnly & ".pdf"
Debug.Print "Processing: " & targetFile
' --- トランザクション制御の開始 ---
On Error GoTo ErrorHandler ' エラーが起きたら ErrorHandler ラベルへジャンプ
' 1. プレゼンテーションを開く
Set pres = pptApp.Presentations.Open(sourceFolder & targetFile, ReadOnly:=msoTrue, WithWindow:=msoFalse)
' 2. PDFとして保存を試みる
' ここでネットワークが切れると、エラーが発生する
pres.ExportAsFixedFormat Path:=targetPath, _
FixedFormatType:=ppFixedFormatTypePDF, _
Intent:=ppFixedFormatIntentPrint
' 3. 成功したら、ファイルを閉じる
pres.Close
Set pres = Nothing
Debug.Print "Successfully exported: " & targetPath
' エラーハンドリングをリセットして次のファイルへ
On Error GoTo 0
NextFile:
targetFile = Dir() ' 次のファイルへ
Loop
MsgBox "全工程が完了しました。", vbInformation
Exit Sub
ErrorHandler:
' --- ロールバック(回復)フェーズ ---
Debug.Print "Error detected on " & targetFile & ": " & Err.Description
' もしファイルが中途半端に作られていたら、削除してクリーンアップする
If fso.FileExists(targetPath) Then
On Error Resume Next ' 削除自体が失敗する場合(ファイルがロックされている等)に備える
fso.DeleteFile targetPath, True
On Error GoTo 0
Debug.Print "Rollback: Incomplete file deleted -> " & targetPath
End If
' 開いているプレゼンテーションがあれば閉じる
If Not pres Is Nothing Then pres.Close
' 次のファイルへ進むためにリセット
Resume NextFile
End Sub
3. プロの視点:コードの「急所」を解説
このコード、ただ動くだけではありません。以下の3つのポイントが「プロの仕事」です。
① `On Error GoTo ErrorHandler` による「脱出路」の確保
初心者のうちは、エラーが出ると「マクロが止まって、どこまで終わったか分からなくなる」ことに恐怖を感じます。
このコードでは、エラーが起きた瞬間に `ErrorHandler` へワープさせ、「失敗したファイルを消す」→「次に進む」という動きを自動化しています。これがレジリエンス(回復力)の正体です。
② `FileSystemObject` による確実なクリーンアップ
`Kill` ステートメントでもファイル削除はできますが、`FileSystemObject` を使うことで、ファイルが存在するかどうかのチェック(`FileExists`)や、読み取り専用属性を無視した削除がより堅牢に行えます。
「ゴミを残さない」という強い意志が、この一行に込められています。
③ `Resume NextFile` による継続性
ここが最も重要です。エラーが起きたからといって、全ての処理を中止するのはもったいないですよね。
`Resume NextFile` を使うことで、「失敗したファイルは掃除して、次のファイルから再開する」という、止まらないパイプラインを実現しています。
4. さらに上を目指すあなたへ:究極の回避策「Staging Pattern」
もし、あなたが「絶対に、1%の破損も許されない」という極限のミッションを任されたら、どうするか?
その答えは、「いきなりネットワークに書き込まない」です。
1. ローカル(自分のPC)のTempフォルダにPDFを作る。
2. 完成した(エラーなく書き込めた)PDFだけを、最後にネットワークへ移動(Move)させる。
ネットワークへの移動は「書き込み」に比べて一瞬で終わるため、通信トラブルに巻き込まれる確率を劇的に下げられます。これを「ステージング・パターン」と呼びます。
' イメージ図
' 1. SaveAs "C:\Temp\result.pdf" (ローカルで安全に)
' 2. If Success Then fso.MoveFile "C:\Temp\result.pdf", "\\Network\result.pdf"
まとめ:制御を掌握すれば、VBAは武器になる
マクロの記録から一歩踏み出し、今回のような「エラーが起きたらどうするか?」「不完全な状態をどう防ぐか?」を考えるようになると、あなたの書くコードの質は劇的に変わります。
- エラーは「防ぐもの」ではなく、「起きた後の動きを設計するもの」
- データの整合性を守ることは、ユーザーの信頼を守ること
この視点を持っていれば、あなたはもう「マクロ使い」ではなく、立派な「自動化エンジニア」です。
さあ、勇気を持って、もっと複雑な、もっと大きな課題に挑戦していきましょう。応援していますよ!
