CorelDRAW VBAを掌握する極限の知見:`Optimization = True` と `EventsEnabled = False` の併用による描画フリーズ防止と高速化の極意
シニアエンジニア、そして企業内システムの自動化を極めんとするアーキテクト諸君。CorelDRAW VBAのパフォーマンス限界に直面したことはないだろうか。
数千、数万に及ぶベクターオブジェクトの動的生成、複雑なパスの結合、一括変形。これらを愚直にデフォルトの実行環境で処理させれば、CorelDRAWのウィンドウは白濁し、OSからは「応答なし」と宣告され、最悪の場合はメモリリークによる強制終了を引き起こす。
CorelDRAWのオブジェクトモデルは強力だが、その裏側にあるレンダリングエンジンとイベントリスナーは、大量一括処理においては最大のボトルネックとなる。
今回は、CorelDRAW VBAのパフォーマンスを極限まで引き上げるための2大禁忌(あるいは特効薬)、`Application.Optimization = True` と `Application.EventsEnabled = False` の併用について、オブジェクトのライフサイクルと内部挙動の観点から徹底的に解剖する。
—
1. なぜCorelDRAWのバッチ処理は遅いのか?(内部挙動の真実)
VBAからCorelDRAWのドキュメントを操作する際、デフォルトの状態では以下の処理が1回のアクションごとに発生している。
1. 画面の再描画(Redraw / Rendering): オブジェクトが1つ追加・変更されるたびに、ビューポートの再計算と画面のピクセル描画が走る。
2. UIイベントの伝播(Event Dispatching): 選択状態の変化、ドキュメントの変更、マウスカーソルの追従など、あらゆる内部イベントがキューに積まれ、処理される。
3. Undoステップの生成(Undo Queue): すべての微細な操作がアンドゥバッファに蓄積され、メモリを急速に圧迫する。
数千個のオブジェクトをループで生成するコードにおいて、これらが毎ループ実行されることを想像してほしい。CPU時間の9割以上が「描画」と「イベント管理」に費やされ、肝心のベクター演算はわずかしか進まない。これが「描画フリーズ」の正体である。
—
2. 2大最適化プロパティのメカニズム
この悪夢を断ち切るのが、`Application` オブジェクトが持つ2つのプロパティだ。
`Optimization = True`
- 効果: 画面の再描画、ウィンドウの更新、およびUndo情報の記録を一時的に完全停止(サスペンド)する。
- 裏側: ドキュメントのDOMツリーに対する変更のみがメモリ上で高速に実行され、ビューへの反映が完全にバイパスされる。
`EventsEnabled = False`
- 効果: CorelDRAWアプリケーション層で発生するすべてのイベント(UIの変更通知、選択変更など)のリスナーを無効化する。
- 裏側: マクロ実行中の予期せぬUI干渉を防ぎ、イベントハンドラの多重起動や無駄な割り込み処理をシャットアウトする。
—
3. 【実践】極限最適化テンプレートコード
実務の現場でそのまま利用できる、堅牢性と高速性を極めたボイラープレートコードを提示する。エラーハンドリング(`On Error`)と組み合わせることで、途中でマクロがクラッシュした際にも描画ロックやイベント無効化が解除されないまま放置される事故(ゾンビ状態)を完全に防ぐ設計にしている。
Sub ExtremeBatchProcess()
Dim startTime As Double
startTime = Timer
‘ 1. アプリケーション層の最適化フラグを退避(環境復元のため)
Dim origOptimization As Boolean
Dim origEvents As Boolean
Dim origScreenUpdates As Boolean
origOptimization = Application.Optimization
origEvents = Application.EventsEnabled
origScreenUpdates = Application.ScreenRefresh
‘ 2. エラーハンドリングの要塞化
On Error GoTo ErrorHandler
‘ — 【最重要】最適化の有効化 —
Application.Optimization = True
Application.EventsEnabled = False
‘ ドキュメントの参照を取得(アクティブドキュメント)
Dim doc As Document
Set doc = ActiveDocument
If doc Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical
GoTo Finally
End If
‘ ワーキングレイヤーの特定
Dim lay As Layer
Set lay = doc.ActiveLayer
‘ — 大量オブジェクト生成シミュレーション (5000個の矩形を一括生成) —
Dim i As Long
Dim sh As Shape
For i = 1 To 5000
‘ 座標を計算して矩形を描画
‘ Optimization有効下では、このループは驚異的な速度で完了する
Set sh = lay.CreateRectangle(i 0.5, i 0.5, i 0.5 + 10, i 0.5 + 10)
‘ 属性の設定(必要に応じて)
sh.Outline.Color.RGBAAssign 255, 0, 0
sh.Fill.ApplyNoFill
‘ ※注意: この間、画面は一切更新されず、選択ハイライトも表示されない
Next i
‘ 3. 強制的な画面の再構築と最適化の解除
‘ まだOptimization = Trueのまま、最終的なドキュメントの状態を整える
doc.ClearSelection
Finally:
‘ — 環境の確実な復元(ライフサイクル管理) —
Application.Optimization = origOptimization
Application.EventsEnabled = origEvents
‘ 明示的な画面リフレッシュ
Application.Refresh
MsgBox “処理完了: ” & Format(Timer – startTime, “0.00秒”), vbInformation
Exit Sub
ErrorHandler:
‘ 異常終了時のフォールバック
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
Resume Finally
End Sub
—
4. チーフアーキテクトが教える、さらなるメモリ最適化の極意
上記のコードだけでも数倍〜数十倍の速度向上が体感できるはずだが、真に巨大なシステム(印刷業界の面付けデータ生成や、数万点のダイカットパス処理など)を扱う場合、以下の知見が明暗を分ける。
オブジェクト変数の即時解放(`Set … = Nothing`)
VBAのガベージコレクションは参照カウント方式をとっている。特にCorelDRAWの `Shape` や `ShapeRange` オブジェクトはCOMコンポーネントであり、メモリ食い虫だ。
ループ内で次々とオブジェクトを変数に代入し、古い参照を残したままにすると、VBAの内部メモリが肥大化し、ページのスワップアウト(ディスクアクセス)が発生して急激にパフォーマンスが低下する。
大量ループの内部で生成したオブジェクト変数は、使い終わりに必ず `Set sh = Nothing` で解放せよ。
Windows APIとの連携による「完全な描画停止」
CorelDRAWの `Application.Optimization = True` でも抑えきれない低レベルのOSメッセージキューの処理を完全にロックしたい場合、Windows APIの `LockWindowUpdate` を併用するアプローチもある(※マルチモニター環境やCorelDRAWのバージョン依存があるため、実運用では十分に検証すること)。
‘ 32bit/64bit両対応のAPI宣言例
If VBA7 Then
Private Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hWndLock As LongPtr) As Long
Else
Private Declare Function LockWindowUpdate Lib “user32” (ByVal hwnd As Long) As Long
End If
‘ 使用時は Application.Handle を渡すことで、CorelDRAWのウィンドウ描画をOSレベルで凍結できる
‘ LockWindowUpdate Application.Handle
‘ (処理終了後に LockWindowUpdate 0 で解除)
—
5. まとめ
CorelDRAW VBAにおける自動化の成否は、「いかにCPUとメモリをCorelDRAW自身のUIレンダリングから解放し、純粋な計算処理に集中させるか」にかかっている。
- `Optimization = True` で描画とアンドゥ履歴の記録を殺す。
- `EventsEnabled = False` で不要なイベントの割り込みを断つ。
- エラーハンドリングを徹底し、異常終了時も必ず環境を復元する。
- ループ内のオブジェクト変数はこまめに `Nothing` 解放する。
この鉄則を体に叩き込むことで、これまで数分かかっていた巨大ベクターデータの処理をわずか数秒へと昇華させることが可能となる。
レガシーなVBAであっても、アーキテクチャの本質を理解していれば、最新のシステムに匹敵する極限のパフォーマンスを引き出すことは十分に可能だ。あなたのコードを、真のプロフェッショナルが書く「圧倒的なスピード」へと到達させたまえ。
