【実務・中級編】Document.Close呼び出し時のSaveChangesパラメータ制御とオブジェクト変数の確実な解放手法 – CorelDRAW VBA解析バイブル

スポンサーリンク

CorelDRAW VBAを掌握する極限の知見:大量ファイル処理におけるメモリリーク完全制圧メソドロジー

開発プロジェクトの現場で、自動化スクリプトが途中で強制終了したり、タスクマネージャーのメモリ使用量が右肩上がりに膨れ上がったりして絶望した経験はないだろうか。

特にCorelDRAW VBAを用いた大量ファイルのバッチ処理において、最もエンジニアを悩ませるのが「ドキュメントのライフサイクル管理の不備によるメモリリーク」だ。

今回は、`Document.Close` メソッドの挙動の真実と、オブジェクト変数を完全に解放して堅牢なシステムを構築するための極限の知見を授ける。

なぜあなたのマクロはメモリリークを起こすのか?

CorelDRAWのCOMオブジェクトモデルは、VBAのガベージコレクション(参照カウント方式)の隙間を容赦なく突いてくる。

多くの開発者が犯す致命的な設計ミスは以下の2点だ。

1. `Document.Close` を呼ぶ際に `SaveChanges` パラメータを適切に制御していない
意図しないダイアログのポップアップによる処理のフリーズ、あるいは無駄なディスクI/Oの発生。
2. ドキュメントを閉じた後も、オブジェクト変数に参照が残ったまま放置されている
CorelDRAWの内部プロセスがメモリ上に残り続け、数千ファイルの処理時には確実にOutOfMemoryを引き起こす。

「ファイルを閉じたから大丈夫」という素朴な甘えは、プロダクション環境では許されない。オブジェクトの生成から消滅(Life Cycle)までのライフラインを、完全にコードで支配しなければならない。

`Document.Close` と `SaveChanges` の正確な制御

まずは、ドキュメントを閉じる際の鉄則を確認する。
`Document.Close` メソッドは、引数を省略するとユーザーに保存確認のダイアログを表示しようとする。自動化バッチにおいてダイアログの出現は「死」を意味する。

‘ 構文の基本
theDoc.Close [SaveChanges As cdrSaveOption = cdrSaveChanges], [FileName]

ここで使用する `cdrSaveOption` 列挙体の挙動を正確に把握せよ。

  • `cdrSaveChanges` : 変更を強制保存して閉じる。
  • `cdrDoNotSaveChanges` : 変更を破棄して閉じる(自動処理で最も多用する)。
  • `cdrSavePrompt` : 保存確認ダイアログを表示する(自動化では絶対に使用してはならない)。

堅牢性極まるプロダクションコード例

以下に、実務の現場でそのまま投入できる、例外処理と完全なメモリ解放を実装したバッチ処理のテンプレートコードを示す。

Option Explicit

Sub ExecuteBatchProcess()
Dim targetFolder As String
Dim fileName As String
Dim srcDoc As Document

‘ 処理対象フォルダのパス(環境に合わせて変更すること)
targetFolder = “C:\Data\CorelBatch\”
fileName = Dir(targetFolder & “.cdr”)

‘ 画面描画とイベントを停止し、処理速度を限界まで引き上げる
Application.Optimization = True
EventsEnabled = False

On Error GoTo ErrorHandler

Do While fileName <> “”
‘ ドキュメントを開く(非表示またはアクティブ化抑制の配慮)
Set srcDoc = Application.OpenDocument(targetFolder & fileName)

‘ —————————————————-
‘ ここに実業務の加工ロジックを記述する
‘ 例: 全シェイプの色をCMYKに変換するなどの処理
‘ —————————————————-
Call ProcessDocument(srcDoc)

‘ 1. 変更を保存せずに閉じる(必要に応じて cdrSaveChanges に変更)
‘ 2. 同時に変数への参照を切る布石とする
srcDoc.Close cdrDoNotSaveChanges

‘ 【最重要】オブジェクト変数の即時解放
Set srcDoc = Nothing

‘ 次のファイルへ
fileName = Dir
Loop

CleanUp:
‘ 最適化フラグを必ず元に戻す
Application.Optimization = False
EventsEnabled = True
MsgBox “バッチ処理が正常に完了しました。”, vbInformation
Exit Sub

ErrorHandler:
‘ 予期せぬエラーが発生した場合でも、メモリリークとプロセスのロックを防ぐ
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical

‘ エラー時もオブジェクトが残っていれば確実に解放
If Not srcDoc Is Nothing Then
On Error Resume Next
srcDoc.Close cdrDoNotSaveChanges
Set srcDoc = Nothing
On Error GoTo 0
End If

Resume CleanUp
End Sub

Private Sub ProcessDocument(ByRef doc As Document)
‘ 渡されたドキュメントに対する安全な操作領域
Dim sh As Shape
For Each sh in doc.Pages(1).Shapes
‘ 処理の例
Next sh
End Sub

チーフアーキテクトが教える、バグを生まない3つの鉄則

1. `Application.Optimization = True` とのセット運用

大量のファイルを扱う場合、CorelDRAWの画面描画やUIイベントの更新は百害あって一利なしだ。処理の最初に `Optimization = True` をかけ、終了時(あるいはエラー時)に必ず `False` に戻すこと。これを怠ると、ドキュメントを閉じてもUIのキャッシュがメモリ上に残存する原因となる。

2. `Set xxx = Nothing` の徹底とスコープ管理

VBAのローカル変数はプロシージャを抜ければ自動解放される……というのは理想論だ。COMオブジェクトの参照カウントが複雑に絡み合うCorelDRAW VBAにおいては、「使い終わった瞬間に明示的に `Nothing` を代入する」のがプロの作法である。
特にループ内でドキュメントを開閉する場合、前のループの残骸がメモリに残ったまま次の `OpenDocument` が走ると、ヒープ領域に致命的な断片化を引き起こす。

3. エラーハンドラー内での二重解放ガード

エラー発生時にジャンプする `ErrorHandler` 内でも、オブジェクト変数が生きていないか必ず `If Not srcDoc Is Nothing Then` で確認し、安全に `Close` と `Set Nothing` を実行すること。例外時こそ、メモリリークの温床になりやすい。

結びにかえて

自動化スクリプトの品質は、「正常系が動くこと」ではなく、「異常系や長時間稼働においていかにリソースを汚さないか」で決まる。

今回伝授した `Document.Close` のパラメータ制御と、徹底的な `Nothing` によるオブジェクト解放のメソドロジーをマスターすれば、CorelDRAW VBAはあなたを裏切らない。強靭で止まらない自動化システムを、その手で構築してほしい。

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