【テクニカル・上級編】【上級者向け】Visioをバックグラウンドで隠蔽起動し、UIを表示せずにPDF変換を行う際の「メモリリーク対策」 – Visio VBA解析バイブル

スポンサーリンク

Visio自動化の暗部:バックグラウンドPDF変換における「メモリの呪縛」を解く

Visio VBAによる帳票生成やPDF変換を自動化している諸君なら、一度は直面したはずだ。数百、数千の図面をループ処理する際、処理が進むにつれて徐々に増大し、やがてVisioプロセスが力尽きてフリーズ、あるいは「メモリ不足」でクラッシュする現象。

巷のチュートリアルは「`Set obj = Nothing` を呼べ」と説くが、あれは気休めに過ぎない。VisioのCOMオートメーションにおいて、メモリリークの正体は「解放されない非可視インスタンスの肥大化」と「COMインターフェースの不完全なクリーンアップ」にある。

今日は、現場で生き残るための「プロセス制御」と「メモリ管理」の極限解法を伝授する。

—

1. なぜ「Close」だけでは足りないのか

VBAで `VisioApp.Quit` を呼び出しても、Windowsのタスクマネージャーを見るとプロセスが残存していることがある。これは、DOM(Document Object Model)の参照がどこかに残っているか、VisioがバックグラウンドでCOMイベントを処理し続けているためだ。

この「ゾンビプロセス」が蓄積することで、システムのリソースは食い潰される。大量処理を行う際、「Visioを起動しっぱなしにする」という設計思想そのものが、そもそも誤りであると断言する。

—

2. 実践:高信頼性PDF変換アーキテクチャ

メモリを安定させる唯一の解は、「一定数処理したらプロセスを強制再起動する」ことだ。また、UIの非表示化には `Application.Visible = False` を使うが、これだけでは不十分なケースがあるため、Windows APIを用いて確実にウィンドウを隠蔽する。

安定稼働のためのVBA実装例

Option Explicit

‘ メモリ監視と再起動を行うラッパー
Private Const MAX_DOCUMENTS As Long = 50 ‘ プロセス再起動のしきい値

Public Sub BatchExportToPDF(fileList As Collection)
Dim i As Long, count As Long
Dim visApp As Visio.Application

count = 0
For i = 1 To fileList.Count
‘ プロセスが未起動、または閾値到達で再起動
If visApp Is Nothing Or count >= MAX_DOCUMENTS Then
Call TerminateVisio(visApp)
Set visApp = CreateObject(“Visio.Application”)
visApp.Visible = False
visApp.AlertResponse = 7 ‘ ダイアログを自動的に閉じる
count = 0
End If

Call ExportSinglePDF(visApp, fileList(i))
count = count + 1
Next i

Call TerminateVisio(visApp)
End Sub

Private Sub ExportSinglePDF(app As Visio.Application, filePath As String)
Dim doc As Visio.Document
Set doc = app.Documents.Open(filePath)

‘ PDF出力処理
‘ 固定パス・ファイル名で出力
doc.ExportAsFixedFormat visFixedFormatPDF, Replace(filePath, “.vsdx”, “.pdf”)

‘ 明示的なドキュメント解放
doc.Close
Set doc = Nothing

‘ ガベージコレクションを促す(VBAでは限定的だが気休めではない)
DoEvents
End Sub

‘ プロセスを確実に抹殺するためのラッパー
Private Sub TerminateVisio(ByRef app As Visio.Application)
If Not app Is Nothing Then
app.Quit
Set app = Nothing
End If
‘ 念のため、実行中のVisioプロセスを強制終了するコマンド
Shell “taskkill /f /im visio.exe”, vbHide
End Sub

—

3. シニアエンジニアが知るべき「更なる深淵」

A. `AlertResponse` の徹底管理

バックグラウンド処理において最も恐ろしいのは、予期せぬエラーダイアログや「フォントがありません」といった警告でプロセスが停止することだ。`app.AlertResponse = 7` を設定することで、Visioは「No」を選択し続け、処理を中断させない。

B. COM参照の完全な遮断

`DoEvents` は、シングルスレッドであるVBAにおいて、OSにコントロールを戻し、COMの解放要求を処理させるための呼吸だ。ループの終端で必ず呼ぶこと。これを怠ると、Visual Studioのデバッガですら追えないメモリリークの温床となる。

C. なぜ「プロセス再起動」が最適解なのか

Visioというアプリケーションは、描画エンジンやキャッシュ機構が非常に重厚である。長時間稼働させると、ドキュメントを閉じた後でも「UNDO履歴」や「内部キャッシュ」がメモリに残留しやすい。これを物理的に「殺して再起動する」ことは、泥臭いが、長時間のバッチ処理における最も確実な「メモリ・リセット」である。

—

結論:システムは「壊れること」を前提に組め

諸君が構築すべきなのは「メモリリークしない完璧なコード」ではない。「メモリリークが発生しても、プロセスを再起動することでシステムが止まらないタフなアーキテクチャ」である。

リソースを使い切るまで粘るシステムは、いずれ必ず死ぬ。リソースを使い切る前に自ら身を引く(再起動する)システムこそが、エンタープライズの現場で生き残る真の自動化エンジニアの仕事だ。

さあ、Visioのプロセスを管理下に置き、その挙動を支配せよ。

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