【テクニカル・上級編】【メモリリーク対策】Document.Close呼び出し時のSaveChangesパラメータの正しい制御とオブジェクト変数のNothingクリア – CorelDRAW VBA解析バイブル

スポンサーリンク

CorelDRAW VBAの「亡霊」を葬れ:Documentオブジェクトのライフサイクルとメモリ解放の深淵

CorelDRAWの自動化を極める過程で、多くの開発者が直面する「見えない壁」がある。マクロを実行するたびにメモリ使用量が増大し、やがてCorelDRAWがフリーズする、あるいはタスクマネージャーに `CorelDRW.exe` がゾンビのように残り続ける現象だ。

これは単なるバグではない。CorelDRAWのオブジェクトモデルにおける「参照カウントの未解決」と「Document終了処理の甘さ」が招く必然である。本稿では、レガシーなVBA環境下において、いかにしてシステムのリソースを完全に制御し、枯れたアーキテクチャを堅牢な自動化エンジンへと昇華させるかを説く。

1. ゾンビプロセスの正体:参照の切断とガベージコレクションの限界

VBAは、COM(Component Object Model)のラッパーに過ぎない。あなたが `Set doc = Application.OpenDocument(…)` と書いた瞬間、メモリ上ではインターフェースへのポインタが確保される。

問題は、`doc.Close` を呼んだだけでは「COMオブジェクトの参照」までが即座に破棄されるとは限らない点にある。特にループ処理で複数のドキュメントを扱う場合、参照を明示的にクリアしない限り、CorelDRAWの内部エンジンは「まだどこかでこのドキュメントが使われているかもしれない」と判断し、メモリを解放しない。

2. 破壊的後処理のベストプラクティス

ドキュメントを閉じる際の `SaveChanges` パラメータは、単なる保存の有無ではない。OSリソースとの同期を強制するトリガーである。

以下に、現場レベルで確実に動作する「完全終了パターン」を示す。

Public Sub SafeDocumentProcessing(ByVal filePath As String)
Dim doc As Document

‘ エラーハンドリングを組み込み、異常終了時にも確実に解放させる
On Error GoTo Cleanup

Set doc = Application.OpenDocument(filePath)

‘ — ここにメインの業務ロジックを記述 —
‘ 例: doc.ActiveLayer.CreateArtisticText …
‘ ————————————

‘ 変更を保存せずに閉じる場合
‘ cdrDoNotSaveChanges: 保存せずに閉じる
doc.Close cdrDoNotSaveChanges

Cleanup:
‘ 1. オブジェクトの明示的解放(必須)
‘ これを忘れると、VBA上の変数が無効なポインタを保持し続ける
Set doc = Nothing

‘ 2. エラー発生時の処理
If Err.Number <> 0 Then
Debug.Print “Error: ” & Err.Description
End If
End Sub

重要なポイント

  • `Set doc = Nothing` の不可欠性: これを省略すると、スコープを抜けるまで参照カウントが減らず、メモリリークの温床となる。
  • `cdrDoNotSaveChanges` の活用: 自動化処理において、中間ファイルを意図せず保存させることはリスクである。明確な意図がある場合を除き、読み込み専用で開き、破棄する運用を徹底せよ。

3. Windows APIによる強制クリーンアップ(極限の知見)

VBA標準の機能だけでは、CorelDRAWの内部キャッシュが解放されないケースがある。特に大量のファイルを連続処理する場合、`DoEvents` だけでは不十分だ。

もしメモリ不足が顕著な場合は、プロセスを監視し、明示的に `GC.Collect` に相当する処理を模倣するか、Windows APIを用いてUIスレッドを休ませる必要がある。

‘ API宣言(モジュール先頭に配置)
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

‘ 連続処理の合間に挟むインターバル
‘ CorelDRAWの内部的な再描画とメモリ管理の同期を待つ
Public Sub ForceMemoryRelease()
DoEvents
Sleep 200 ‘ 200msの休止でCOMの解放を待機させる
End Sub

4. チーフアーキテクトからの提言:保守性の高い設計へ

VBAによる自動化で最も避けるべきは、「単一のプロシージャ内に全てのロジックを詰め込むこと」である。

1. 分離: ドキュメントの開閉(ライフサイクル管理)と、描画ロジック(ビジネスロジック)を必ず関数として分割せよ。
2. 監視: 可能な限り、処理対象のドキュメント数は定数または設定ファイルで制御し、無限ループを発生させない設計を行うこと。
3. 検証: 本番環境投入前に、タスクマネージャーで「マクロ実行前」と「マクロ実行後(かつ終了後)」の `CorelDRW.exe` のメモリ消費量を比較せよ。ここが減っていなければ、あなたのコードは未完成だ。

CorelDRAW VBAは古い技術かもしれない。しかし、オブジェクトモデルの挙動を深く理解し、COMの特性を制御下に置くことができれば、それは現代のどの言語よりも強力な「直感的」なツールへと変貌する。

メモリを制する者が、自動化を制する。諸君の健闘を祈る。

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