CorelDRAW VBAを掌握する極限の知見:重厚長大なブール演算バッチ処理の高速化とメモリマネジメント
CorelDRAW VBAの自動化において、最もエンジニアを絶望の淵に追い込むのは、大量のベクターデータに対する「溶接(Weld)」「トリム(Trim)」「結合(Intersect)」といった幾何学ブール演算のループ処理だ。
数個のシェイプであれば瞬時に終わる処理も、数千、数万というデザインアセットのバッチ処理に組み込んだ途端、処理速度は幾何級数的に低下し、最悪の場合はCOM例外(Out of Memory)やCorelDRAW本体のサイレントクラッシュを引き起こす。
なぜなら、VBAの背後でうごめくCorelDRAWのCOMオブジェクトモデルは、不適切な参照保持によってヒープ領域を肥大化させ、幾何学演算のたびに発生する複雑なノードツリーの再計算が、GC(ガベージコレクション)のタイミングを狂わせるからだ。
本稿では、レガシーかつ強力なCorelDRAWのエンジンを限界まで絞り込み、大規模なベクター変形バッチ処理を安定稼働させるための「極限の知見」を実務コードとともに公開する。
—
1. ブール演算におけるパフォーマンス劣化の根本原因
`Shape.Weld` や `Shape.Trim` といったメソッドは、単なるプロパティの書き換えではない。これらは内部でC++製の重厚なカーネルを呼び出し、パスの交差判定、トポロジーの再構築、重なり合うノードの統合などを動的に実行している。
バッチ処理でこれらが遅延・破綻する主な要因は以下の3点に集約される。
1. 暗黙的なオブジェクト参照の蓄積(メモリリーク)
`ActiveLayer.CreateRectangle` やブール演算結果として返される新規 `Shape` オブジェクトを、ローカル変数に適切に格納・解放しないままループを回すと、COMラッパーがメモリ上に残存し続ける。
2. 画面描画(Screen Updating)とイベントのオーバーヘッド
演算が1回走るごとにCorelDRAWのビューポートが再描画され、UIスレッドがブロックされる。
3. アクティブ選択への過度な依存
`ActiveDocument.Selection` を乱用すると、ドキュメントのセレクションマネージャが重い同期処理を強いられる。
—
2. 高速バッチ処理を実装するための3大鉄則
鉄則①:画面描画と自動更新の完全シャットダウン
処理の開始前には必ずアプリケーションの描画を止め、イベントを抑制する。これにより、CPUリソースの100%を幾何学演算エンジンに集中させることが可能になる。
鉄則②:レイヤーコンテキストの直接操作と `Active` の排除
`ActiveSelection` や `ActiveShape` は一切使わない。ドキュメントオブジェクトから明示的にレイヤーやシェイプの参照を辿り、インデックスベースまたはオブジェクト参照で直接叩く。
鉄則③:演算ごとの即時参照解放(オブジェクトのライフサイクル管理)
ブール演算の戻り値は常に新しいシェイプである。不要になった古いシェイプは即座に `.Delete` し、変数には `Nothing` を代入してCOM参照カウンタを即座にデクリメントする。
—
3. 実装コード:堅牢性と速度を極めたブール演算バッチエンジン
以下に、実務の現場でそのまま投入可能な、数千個のシェイプ群に対して安全かつ高速に溶接・トリム処理を行うバッチ処理のテンプレートを示す。
Option Explicit
Public Sub ExecuteHighSpeedBooleanBatch()
Dim startTime As Double
startTime = Timer
‘ — 1. 最適化のための環境設定 —
Dim appRef As CorelDRAW.Application
Set appRef = CreateObject(“CorelDRAW.Application”)
‘ 画面描画とイベントの完全停止(パフォーマンス劇的改善の鍵)
appRef.Optimization = True
appRef.EventsEnabled = False
On Error GoTo ErrorHandler
Dim doc As CorelDRAW.Document
Set doc = appRef.ActiveDocument
If doc Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical
GoTo Cleanup
End If
Dim targetLayer As CorelDRAW.Layer
Set targetLayer = doc.ActiveLayer
‘ — 2. バッチ処理対象の取得と安全な走査 —
Dim shps As CorelDRAW.Shapes
Set shps = targetLayer.Shapes
Dim i As Long
Dim baseShape As CorelDRAW.Shape
Dim targetShape As CorelDRAW.Shape
Dim resultShape As CorelDRAW.Shape
‘ ※注意: コレクションを逆順でループすることで、要素削除時のインデックスズレを防ぐ
For i = shps.Count – 1 To Step – 2
If i >= 1 Then
Set baseShape = shps(i)
Set targetShape = shps(i – 1)
‘ 有効なカーブオブジェクト同士であるか検証
If baseShape.Type = cdrCurveShape And targetShape.Type = cdrCurveShape Then
‘ 幾何学演算の実行(ここではWeldを例とする)
‘ ※TrimやIntersectの場合は baseShape.Trim targetShape のように記述
Set resultShape = baseShape.Weld(targetShape, False, False)
If Not resultShape Is Nothing Then
‘ 演算元となった古いシェイプを完全に削除
baseShape.Delete
targetShape.Delete
‘ 参照変数のクリーンアップ
Set baseShape = Nothing
Set targetShape = Nothing
Set resultShape = Nothing
End If
End If
End If
Next i
Cleanup:
‘ — 3. 環境の復元とメモリ解放 —
If Not appRef Is Nothing Then
appRef.EventsEnabled = True
appRef.Optimization = False
appRef.Refresh
End If
Set targetLayer = Nothing
Set doc = Nothing
Set appRef = Nothing
MsgBox “バッチ処理が完了しました。 処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume Cleanup
End Sub
—
4. エンジニアリングの深層:なぜこのコードが「落ちない」のか
上記のコードには、単なる文法以上のアーキテクチャ上の工夫が施されている。
コレクションの逆順ループ (`Step -2`)
ベクターグラフィックスのバッチ処理で最も頻繁に起こるバグが、要素削除に伴う「インデックスのズレ(Subscript out of range)」である。
上から順(1, 2, 3…)に処理して要素を削除していくと、配列やコレクションのインデックスが狂い、メモリ違反を引き起こす。
末尾から逆順に処理を進めることで、削除の影響を受けない安全なイテレーションが担保される。
`Optimization = True` の強烈な効果
CorelDRAWの `Application.Optimization` プロパティは、GUIの再描画だけでなく、Undoスタックの構築を一時的に抑制・軽量化する。
数千回のブール演算のたびにUndo履歴をメモリに積んでいけば、数ギガバイトのメモリが一瞬で消費され、OSの仮想メモリを圧迫する。これを抑止することが、クラッシュを防ぐ最大の防壁となる。
—
5. さらに先へ:外部システム連携とヘッドレス運用への布石
このVBAによる最適化手法を極めれば、次はWindows Script Host (WSH) や外部の .NET (C#) アプリケーションからCorelDRAWをCOMサーバーとして「完全バックグラウンド(ヘッドレス)」で起動し、UIを持たない真のエンタープライズ・バッチパイプラインを構築することが可能になる。
// C# から CorelDRAW の最適化エンジンを叩く概念コード
CorelDRAW.Application cdr = new CorelDRAW.Application();
cdr.Optimization = true;
cdr.EventsEnabled = false;
// サーバーサイドでの高速ベクター処理の実行…
CorelDRAW VBAはレガシーな技術と侮られがちだが、その背後にあるオブジェクトモデルとC++カーネルの挙動を完全に掌握したエンジニアの手にかかれば、現代のモダンなDTP自動化基盤としても十分に渡り合えるポテンシャルを秘めている。
妥協のないコード設計とメモリ管理により、あなたのデスクトップ自動化環境を「絶対に落ちない要塞」へと進化させてほしい。
