【Visio VBA極意】PDF出力の「ファイルロック問題」を完全制圧するリトライ・待機ロジック
こんにちは。業務自動化の現場で、Visioの図面と格闘し続けている皆さんに、一つお聞きしたいことがあります。
「PDF書き出しの途中で『ファイルが使用中です』とエラーが出て、マクロが止まってしまったことはありませんか?」
これ、自動化エンジニアにとって「あるある」ですが、放置してはいけない致命的な問題です。特に、生成したPDFを即座にメール送信したり、共有フォルダへコピーしたりする自動化パイプラインにおいて、このエラーは天敵。
今回は、単にコードを動かすだけでなく、「外部プロセスの状態をどうハンドリングするか」という、プロのエンジニアが必ず通る「堅牢性」の極意を伝授します。
—
なぜ、PDF出力は失敗するのか?
結論から言うと、「OSのファイルロック」と「Visioの非同期処理(のような挙動)」のタイムラグが原因です。
VBAで `ExportAsFixedFormat` を実行した瞬間、OSはファイルを作成しようとしますが、直前のプロセス(例えば、以前開いていたPDFビューアや、ウイルス対策ソフトのスキャン)がそのファイルを掴んでいると、アクセス権限で弾かれます。
ここで「マクロを一度止めて、手動でリトライ」しているうちは、まだ初級者。今回は、「ファイルが空くまで粘り強く待機し、それでもダメなら潔く諦める」というインテリジェントなロジックを実装します。
—
堅牢なPDF書き出しロジックの全貌
まずは、以下のコードをご覧ください。これが「現場で生き残るためのコード」です。
Option Explicit
‘ PDF出力の最大待機時間(秒)
Private Const MAX_WAIT_TIME As Integer = 10
Public Sub ExportVisioToPdfRobust(doc As Visio.Document, outputPath As String)
Dim startTime As Single
Dim isSuccess As Boolean
startTime = Timer
isSuccess = False
‘ 1. ファイルがロックされているか確認しつつリトライ
Do While Timer – startTime < MAX_WAIT_TIME
On Error Resume Next ' エラーを一旦無視してファイル開閉テスト
' ファイルが開けるか試す(排他制御の確認)
Dim fNum As Integer
fNum = FreeFile
Open outputPath For Append As #fNum
Close #fNum
If Err.Number = 0 Then
' ロックが解除された!書き出し開始
On Error GoTo 0
doc.ExportAsFixedFormat visFixedFormatPDF, outputPath
isSuccess = True
Exit Do
End If
On Error GoTo 0
DoEvents ' OSに制御を戻し、CPU負荷を抑える(重要!)
Loop
' 2. 結果の判定
If isSuccess Then
MsgBox "PDF出力が完了しました:" & outputPath, vbInformation
Else
MsgBox "エラー:指定時間は待機しましたが、ファイルがロックされています。", vbCritical
End If
End Sub
---
コード解説:なぜこの書き方なのか?
1. `Open … For Append` のトリック
これがプロの知恵です。「ファイルが書き込める状態か?」を確認する最も手っ取り早い方法は、実際にファイルを「追加書き込みモード」で開いてみることです。もし他のアプリが掴んでいれば、ここでエラーが発生します。これを利用して、ロック状態を検知しています。
2. `DoEvents` の魔法
このキーワードを忘れると、PCがフリーズしたような状態になります。`DoEvents` は「OSさん、今のうちに他の処理(描画更新やマウス操作など)をやっていいよ」と許可を与えるコマンドです。これをループ内に入れることで、PCを固まらせずにスマートに待機できます。
3. `On Error Resume Next` と `On Error GoTo 0` のセット
エラーが発生することを前提とした処理(今回のようなロック確認)では、一時的にエラーを無視する必要があります。しかし、そのまま放置するのは絶対にNG。必ず `GoTo 0` で通常の「エラー発生時に止まる」モードに戻しましょう。これを怠ると、後続のバグが見抜けなくなります。
—
さらに上のレベルを目指すあなたへ
このコードは、いわば「PDF出力の盾」です。しかし、さらに精度を高めるなら以下の工夫も検討してみてください。
- 待機間隔の調整: `Sleep` 関数(Windows API)を呼び出し、`DoEvents` の間に数十ミリ秒のインターバルを入れると、よりCPUに優しい挙動になります。
- ファイルパスの正規化: ファイルパスに特殊文字や、長すぎるパスが含まれていないかを事前にバリデーションする関数を作っておくと、より完璧です。
まとめ:自動化とは「失敗を予測すること」
初心者の方は「コードが動くこと」を目指しますが、熟練のエンジニアは「いかに失敗しても、システムを壊さず、適切に終了できるか」を考えます。
PDFのロック解除を待つという、この小さな工夫一つで、あなたの作ったマクロは「たまにエラーが出る困ったマクロ」から、「夜間に放置しても確実にタスクを完遂する頼れるツール」へと進化します。
ぜひ、あなたの現場のVisioファイルに、この「待機ロジック」を組み込んでみてください。ここをクリアすれば、もうあなたは初心者ではありません。自信を持って、次の自動化の海へ漕ぎ出しましょう!
