CorelDRAW VBAの深淵:再帰アルゴリズムで「グループの呪縛」を解き放つ
CorelDRAWで外部データとの連携を試みた際、最も開発者を絶望させるのは「複雑にネストされたグループ構造」です。サードパーティ製のCAMソフトやWeb向けSVGコンバータ、あるいは独自のデータベース連携処理において、階層が深いデータはエラーの温床となります。
「グループを解除してフラットにする」という単純な操作を、なぜ手動ではなくVBAで書くのか。それは、「構造を破壊せず、かつ階層を消滅させる」という矛盾した要件を、機械的な精度で実行するためです。
今日は、業務自動化エンジニアの現場で培った「安全かつ堅牢なフラット化アルゴリズム」を伝授します。
—
1. なぜ「単純なループ」では破綻するのか
初心者が陥りがちなミスは、`Group.Ungroup` を安易に繰り返すことです。しかし、これには致命的な欠陥があります。
- インデックスの喪失: グループを解除した瞬間、元のオブジェクトのインデックスが変わるため、ループ処理が迷子になります。
- スタックオーバーフロー: シンボルインスタンスや極端に深いネストは、再帰の終了条件を誤るとメモリを食いつぶします。
- レイヤーの断絶: グループ内に異なるレイヤーに跨がるオブジェクトが存在する場合、安易なフラット化は階層構造を破壊し、本来のレイヤー情報を消失させます。
我々が目指すべきは、「階層を辿り、フラットなレイヤー構造へ『転送』する」という設計思想です。
—
2. 堅牢な再帰フラット化エンジンの実装
以下のコードは、選択されたすべてのオブジェクトを走査し、グループやシンボルを分解して、指定したターゲットレイヤーへフラットにコピーするプロダクションコードです。
‘ CorelDRAW VBA: Recursive Shape Flattener
‘ 複雑な構造を解析し、単一レイヤーへフラットに再構築する
Public Sub FlattenShapesToLayer()
Dim doc As Document
Dim targetLayer As Layer
Set doc = ActiveDocument
‘ 念のため実行前にUndoグループを作成
doc.BeginCommandGroup “Flatten Hierarchy”
‘ 出力先のレイヤーを指定(存在しなければ作成)
Set targetLayer = doc.ActivePage.CreateLayer(“Flattened_Data”)
‘ 選択オブジェクトを再帰的に処理
Dim s As Shape
For Each s In doc.SelectionRange
ProcessShape s, targetLayer
Next s
doc.EndCommandGroup
End Sub
‘ 再帰関数: シェイプを判定し、グループなら分解、そうでなければコピー
Private Sub ProcessShape(sh As Shape, destLayer As Layer)
‘ シンボルインスタンスの分解(必要に応じて)
If sh.Type = cdrSymbolShape Then
sh.Symbol.Detach
End If
‘ グループかどうかを判定
If sh.Type = cdrGroupShape Then
Dim subSh As Shape
‘ グループ内の全オブジェクトに対して再帰呼び出し
For Each subSh In sh.Shapes
ProcessShape subSh, destLayer
Next subSh
Else
‘ グループ以外(カーブ、テキスト、ビットマップ等)はターゲットへコピー
‘ CloneではなくCopyで独立した実体を作成するのが鉄則
sh.Copy
destLayer.Paste
End If
End Sub
—
3. 実務で生き残るための設計上の注意点
このコードを現場で運用する際、以下の3点に注意してください。
① 座標系の維持(グローバル座標への変換)
上記コードは簡略化のため`Copy & Paste`を使用していますが、厳密な座標保持が必要な場合は `sh.PositionX`, `sh.PositionY` を直接参照し、ルートレベルでの配置を計算する必要があります。グループ内の相対座標は、親の座標を積算することで求められます。
② シンボルインスタンスの「罠」
`cdrSymbolShape` は単なるグループではありません。マスター定義へのリンクです。もし元のシンボル構造を維持したままフラット化したい場合は、`Detach` せずにプロパティだけを抽出するロジックが必要になります。現場の要件に応じて `Detach` するか否かを選択してください。
③ データベース連携時のID管理
この処理でフラット化した後、外部アプリへ渡す際には「どのオブジェクトが元々どのグループに属していたか」というメタデータが消滅します。
もし必要であれば、フラット化する前に `sh.ObjectData` にGUIDを付与し、フラット化した後のオブジェクトにもそのIDを継承させる「メタデータ追跡アルゴリズム」を組み込むのが、真にプロフェッショナルな実装です。
—
まとめ:自動化の先にあるもの
再帰関数を使いこなすことは、CorelDRAWの内部構造(ドキュメントモデル)を支配することと同義です。今回紹介した「分解して転送する」というアプローチは、単なるフラット化に留まらず、データのクレンジングやフォーマット変換の強力な基盤となります。
「動けばいい」コードは誰にでも書けますが、「将来の仕様変更やデータ構造の破綻を予見して書く」のがアーキテクトの仕事です。ぜひ、この再帰ロジックをあなたの武器に加えてください。
次回の記事では、このフラット化されたデータをJSON形式でエクスポートし、外部のPython環境と連携するパイプラインについて解説する予定です。お楽しみに。
