CorelDRAW VBAの「死」を回避せよ:メモリリークとゾンビプロセスを根絶する極限バッチ処理術
CorelDRAWのVBAで数千個のファイルをバッチ処理しようとした際、数時間後に「メモリ不足」や「CorelDRAWが応答なし」で落ちる経験をしたことはないだろうか?
多くの開発者は、`Document.Close` を呼べばメモリが解放されると信じている。だが、それは幻想だ。VBAの背後にあるCOMオブジェクトの参照カウントは、甘い実装をすれば必ず残骸を撒き散らし、やがてWindowsのプロセスを「ゾンビ」化させる。
本稿では、数万規模のベクターファイルを、安定して、かつ高速に処理し続けるための「プロフェッショナルなメモリ管理術」を伝授する。
—
1. なぜあなたのコードは「メモリの海」に溺れるのか
VBAのガーベッジコレクションは、C#やPythonのように優秀ではない。特にCorelDRAWのオブジェクトモデルにおいて、以下は「死」への直行便だ。
- グローバル変数の安易な保持: `Document` や `Layer` をグローバル変数に格納し続けると、参照カウントがゼロにならず、メモリが解放されない。
- イベントの放置: `Document.Close` を呼んでも、イベントハンドラや特定のCOMインターフェースがメモリ上に残留する。
- プロセスの蓄積: 巨大なファイルを扱う際、`Application.Quit` を適切に制御せず、次の処理へ遷移すると、バックグラウンドで隠れたプロセスがメモリを食いつぶす。
—
2. ゾンビ化を防ぐ「堅牢なバッチ処理」の鉄則
バッチ処理において最も重要なのは、「1ファイルごとに完全に環境をリセットすること」だ。
鉄則:リソースの明示的な破棄(Nothing)
VBAでは `Set obj = Nothing` を単に書けばいいと思っているかもしれないが、重要語は「順序」だ。子要素から親要素へ、逆順に解放するのが鉄則である。
堅牢なコードパターン(プロダクションレベル)
以下のコードは、数千個のCDRファイルを安全に処理するためのテンプレートだ。
‘ ———————————————————
‘ メモリリークを撲滅するバッチ処理の核となる設計
‘ ———————————————————
Public Sub ProcessBatchFiles(ByVal folderPath As String)
Dim fso As Object: Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object: Set folder = fso.GetFolder(folderPath)
Dim file As Object
‘ 処理のメインループ
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “cdr” Then
If Not ProcessSingleFile(file.Path) Then
‘ エラー発生時はログ出力し、処理を中断させない設計
Debug.Print “Failed: ” & file.Path
End If
End If
Next file
‘ オブジェクトの明示的破棄
Set folder = Nothing
Set fso = Nothing
End Sub
Private Function ProcessSingleFile(ByVal filePath As String) As Boolean
Dim doc As CorelDRAW.Document
On Error GoTo Cleanup
‘ CorelDRAWのドキュメントをオープン
Set doc = Application.OpenDocument(filePath)
‘ — ここに具体的な加工処理を記述 —
‘ 例: doc.Export …
‘ 処理終了後、即座にクローズ
doc.Close
Set doc = Nothing
ProcessSingleFile = True
Exit Function
Cleanup:
‘ 強制的な解放
If Not doc Is Nothing Then
doc.Close
Set doc = Nothing
End If
ProcessSingleFile = False
End Function
—
3. なぜ「Application.Quit」が必要なのか
数千個のファイルを処理する場合、CorelDRAW自体が内部的に抱えるメモリ(キャッシュやUndoバッファ)が、どれだけコードを綺麗に書いても肥大化する。
「定期的にプロセスを再起動する」のが、最も現実的かつ最強の解決策だ。
- 100ファイル処理するごとに: VBScriptからCorelDRAWを再起動するラッパーを用意する。
- VBScript経由の実行:
1. VBScriptがCorelDRAWを起動。
2. VBAのマクロを呼び出し、100ファイル処理させる。
3. 処理完了後、CorelDRAWを閉じる。
4. VBScriptが再度CorelDRAWを起動し、次の100ファイルを処理。
この「サンドボックス化」こそが、業務自動化エンジニアが到達すべき最終防衛ラインである。
—
4. 最後に:エンジニアとしての心構え
「コードが動くこと」と「コードが壊れないこと」の間には、埋められない深い溝がある。
メモリリークを放置することは、会社の大切なインフラに対する冒涜だ。VBAは古い言語だが、その背後にあるCOMの仕組みを正しく理解すれば、CorelDRAWを最強のグラフィック・オートメーション・エンジンへと変貌させることができる。
次にあなたが書くコードは、ただの「自動化ツール」ではなく、「何千時間もの運用に耐えうる堅牢なシステム」であるべきだ。
コードを書け。そして、そのコードがシステムを殺さないことを確認せよ。これが、プロフェッショナルの仕事だ。
