CorelDRAW VBAを掌握する極限の知見
大量パスデータのブール演算(結合・溶接・交差)を極限まで高速化する実務自動化設計
開発プロジェクトの現場において、「手作業では何時間もかかる複雑な形状の結合や切り抜き処理を自動化してほしい」という要求は、グラフィック制作の現場から頻繁に持ち込まれる難題だ。
数百、数千におよぶパスデータに対し、UI上からマウス操作で「溶接 (Weld)」や「結合 (Combine)」、「交差 (Intersect)」を実行していく…。これはエンジニアの目から見れば、最も排除すべき「CPUと人間の時間を同時に浪費するアンチパターン」に他ならない。
CorelDRAW VBAにおいて、ブール演算は正しく実装しなければ「メモリリーク」「意図しない形状崩壊」「フリーズ」を引き起こす地雷原となる。本稿では、中級者から一歩抜け出し、プロダクション環境で耐えうる堅牢かつ超高速な一括ブール演算処理のアーキテクチャを伝授する。
—
1. なぜ「ナイーブなループ処理」は破綻するのか?
多くの開発者が最初に書くコードは、次のようなものだろう。
‘ 【アンチパターン】絶対にやってはいけない実装
Dim s As Shape
For Each s in ActivePage.Shapes
‘ 選択して溶接する処理(描画更新が走り、オブジェクト参照が破壊される)
s.CreateSelection
ActiveDocument.Weld s2
Next s
このアプローチが実務で必ず破綻する理由は3点ある。
1. 画面描画(Redraw)のオーバーヘッド: ループのたびにUIが再描画され、処理速度が桁違いに低下する。
2. オブジェクト参照の失効(Dangling References): ブール演算を実行した瞬間、元のシェイプは消滅し、新しい単一(またはグループ)のシェイプが生成される。VBAのポインタ参照が宙ぶらりんになり、ランタイムエラーや予期せぬ挙動を誘発する。
3. セレクション依存の脆弱性: `ActiveDocument.Selection`に依存したコードは、ユーザーが誤って別ウィンドウをクリックしたりフォーカスが外れたりしただけで崩壊する。
—
2. プロダクションコードの要件:堅牢な設計思想
実務で稼働するツールを構築するためには、以下の設計原則を遵守しなければならない。
- 画面描画の完全な抑制: `Optimization = True` を活用し、CPUサイクルを計算だけに集中させる。
- ShapeRangeによるバッチ処理: 単体シェイプではなく、`ShapeRange`オブジェクトを生成してメモリ上で一括操作する。
- エラーハンドリングとトランザクション的思考: 演算途中で不正なパス(自己交差やオープンパスなど)に遭遇しても、処理全体がクラッシュしないフォールトトレランス性を持たせる。
—
3. 実装コード:大量パス一括溶接・結合エンジン
以下のコードは、アクティブページ上の指定レイヤーにある全パスデータを効率的にグループ化し、一括で溶接(Weld)処理を行うプロダクションクオリティのマクロである。
Option Explicit
Public Sub ExecuteHighSpeedWeld()
‘ 処理開始時刻の記録(パフォーマンス計測用)
Dim startTime As Double
startTime = Timer
‘ 1. コアエンジンの最適化(描画停止・イベント抑制)
EventsEnabled = False
CorelDRAW.Optimization = True
ActiveDocument.BeginCommandGroup “大量パス一括溶接処理”
On Error GoTo ErrorHandler
Dim srTarget As ShapeRange
Set srTarget = New ShapeRange
‘ 2. 処理対象の収集(例として特定のレイヤー、またはページ上の全カーブシェイプ)
Dim s As Shape
For Each s In ActivePage.Shapes
‘ クローズドパス(曲線)のみを対象とする
If s.Type = cdrCurveShape Then
srTarget.Add s
End If
Next s
‘ ターゲットが2つ以上なければ処理終了
If srTarget.Count < 2 Then
MsgBox "処理対象となるパスが不足しています。", vbExclamation, "処理中断"
GoTo CleanUp
End If
' 3. ブール演算(溶接)の実行
' CorelDRAW VBAの Weld メソッドは、ShapeRangeの最初のシェイプを基準に統合する
Dim resultShape As Shape
Set resultShape = srTarget(1).Weld(srTarget, False, False)
' 4. 結果の検証
If Not resultShape Is Nothing Then
resultShape.Fill.UniformColor.RGBACol = RGB(255, 0, 0) ' 視覚的確認用
MsgBox "一括溶接が完了しました。処理時間: " & Format(Timer - startTime, "0.00") & " 秒", vbInformation, "完了"
Else
Err.Raise 9999, "WeldProcess", "ブール演算エンジンが有効な形状を生成できませんでした。パスの構造を確認してください。"
End If
CleanUp:
' 5. 環境の復元
ActiveDocument.EndCommandGroup
CorelDRAW.Optimization = False
EventsEnabled = True
ActiveDocument.Windows(1).Refresh
Exit Sub
ErrorHandler:
' 異常系ハンドリング
MsgBox "エラーが発生しました [" & Err.Number & "]: " & Err.Description, vbCritical, "致命的なエラー"
Resume CleanUp
End Sub
---
4. チーフアーキテクトからの実務アドバイス
大量データ処理におけるメモリ管理の罠
数千個のパスを一度に `Weld` や `Intersect` にかけると、CorelDRAWの内部ジオメトリエンジンがメモリ不足(Out of Memory)を起こすことがある。もし処理対象が膨大であるならば、バッチ分割処理(Chunking)を取り入れるべきだ。例えば、100個ずつ `ShapeRange` を分割して小分けに溶接し、最後にそれらを結合するアルゴリズムを組むことで、リソース枯渇を完全に防ぐことができる。
外部データ(CSV / データベース)連携時の注意点
もし外部のCSVやデータベースから座標やSVGパスデータを動的にインポートしてブール演算を行う場合、インポート直後のパスは「結合されていないサブパス」や「方向が逆転しているパス」が含まれていることが多い。ブール演算をかける前に必ず `.Simplify` や `.ClosePath` をプログラム側から明示的に呼び出し、パスのトポロジを健全化する前処理をパイプラインに組み込むこと。これが、バグゼロの自動化システムを作り上げる唯一にして最大の秘訣である。
妥協のない設計とコードによって、手作業の悪夢を「一瞬の魔法」に変えてほしい。
