Visioの自動化でメモリが溶ける? プロセスを「使い捨てる」極限のPDF変換アーキテクチャ
業務自動化の現場において、VisioのPDF変換は「鬼門」です。数百枚の図面をループ処理でPDF化しようとすると、最初は軽快に動くのに、10枚、20枚と進むうちにCPU負荷が跳ね上がり、メモリ使用量が肥大化し、最終的には「Visioが応答なし」になる。
多くの開発者は、この現象を「Visioの仕様」として諦め、PCを再起動しては再開する泥臭い運用で回避しています。しかし、それは設計の敗北です。
今日は、Visioを「単なるライブラリ」として扱い、メモリを完全に解放してプロセスを使い捨てる「プロセス分離型・PDF変換アーキテクチャ」を伝授します。
—
1. なぜVisioのメモリは解放されないのか?
VisioのCOMオブジェクトは、明示的に`Quit`メソッドを呼んでも、バックグラウンドのプロセスが完全には消滅しないことが多々あります。特に、`ExportAsFixedFormat`メソッドのような重い処理を繰り返すと、内部のキャッシュやドキュメント参照がスタックし、メモリリークを誘発します。
解決策は明確です。 1つのプロセスに全責任を負わせるのではなく、「1ドキュメント処理ごとにプロセスを再生成する」のです。
—
2. 【設計指針】堅牢な自動化のための鉄則
1. Late Binding(遅延バインディング)の回避: 参照設定を使用し、型安全を確保する。
2. プロセスの隔離: PDF変換用の子プロセスを生成し、処理後に`Quit`とオブジェクトの`Nothing`代入を確実に行う。
3. 例外ハンドリングの徹底: 万が一のクラッシュに備え、プロセス監視を行う。
—
3. 実践コード:堅牢なPDF変換コントローラー
このコードは、メインの処理ルーチンから呼び出される「PDF変換エンジン」です。
‘ 参照設定: Microsoft Visio 16.0 Type Library
Option Explicit
Public Sub ConvertVisioToPdf(ByVal sourcePath As String, ByVal destPath As String)
Dim vApp As Visio.Application
Dim vDoc As Visio.Document
‘ 1. プロセスを新規起動(隠蔽状態)
Set vApp = New Visio.Application
vApp.Visible = False
vApp.AlertResponse = 7 ‘ ダイアログを自動で「いいえ」にする
On Error GoTo ErrorHandler
‘ 2. ファイルを開く(読み取り専用推奨)
Set vDoc = vApp.Documents.OpenEx(sourcePath, visOpenRO + visOpenNoWorkspace)
‘ 3. PDFエクスポート実行
vDoc.ExportAsFixedFormat visFixedFormatPDF, destPath, _
visDocFromVisioPages, visDocAllPages, , , , , , , False
CleanUp:
‘ 4. オブジェクトの明示的破棄と終了
If Not vDoc Is Nothing Then vDoc.Close
If Not vApp Is Nothing Then
vApp.Quit
Set vApp = Nothing
End If
Exit Sub
ErrorHandler:
Debug.Print “Error: ” & Err.Description
Resume CleanUp
End Sub
—
4. 【上級テクニック】連続処理の制御フロー
大量のファイルを処理する場合、上記関数を呼び出すメインルーチンで「進捗管理」と「リソース監視」を分離します。
Public Sub BatchProcessPdf(targetFolder As String)
Dim fso As Object: Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object: Set folder = fso.GetFolder(targetFolder)
Dim file As Object
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “vsdx” Then
‘ ここで毎回新しいプロセスが立ち上がり、処理後に消える
‘ メモリはプロセス終了と共にOSへ返還される
Call ConvertVisioToPdf(file.Path, Replace(file.Path, “.vsdx”, “.pdf”))
‘ 念のための待機(OSのプロセス解放を待つ)
DoEvents
End If
Next
End Sub
—
5. 運用上の極意
- データベース連携: もしファイルパスがDBにあるなら、処理開始前に `Dir()` 関数などでファイル存在確認を徹底してください。Visioの `Open` でエラーを出すと、バックグラウンドプロセスがゾンビ化するリスクが極めて高くなります。
- 非表示起動の罠: `Visible = False` にしても、プリンタドライバの警告やフォントの埋め込み確認ダイアログが出ると処理が止まります。`AlertResponse = 7` は必須の処方箋です。
- パフォーマンスとのトレードオフ: プロセス起動にはコストがかかります。数千枚単位の処理であれば、10〜20ファイルごとに一度ループを抜けて、メインのExcel/Access側の `DoEvents` を挟むか、一度アプリを再起動させる「リセット戦略」を組み合わせるのが、プロのエンジニアの流儀です。
最後に
「コードが動く」ことと「業務を止めない」ことは次元が違います。
Visioのバックグラウンド処理は、いかにして「ゴミ(残存プロセス)を残さないか」というクリーンな設計思想に集約されます。
このコードをあなたのプロジェクトに実装し、メモリ不足に悩まされる日々から卒業してください。それが、自動化エンジニアとしての「格」を上げる第一歩です。
