【入門編】【中級者向け】複雑にネストされたグループ構造とシンボルインスタンスを再帰関数で完全に分解し、フラットなレイヤー階層へ再構築する処理 – CorelDRAW VBA解析バイブル

スポンサーリンク

こんにちは!CorelDRAW VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して図形を動かすだけのステージは、もう卒業しましたね。

実務で他社から受け取ったベクターデータを開いてみて、絶望した経験はありませんか?
「グループの中にグループ、さらにその中にシンボルインスタンスが何重にもネストされていて、中のパスを1つ修正するだけで一苦労……」
そんな複雑怪奇な階層構造を、プログラムの力で一網打尽にし、すべての図形を根こそぎ最上位のフラットなレイヤーへ引きずり出す――今回は、そんな「再帰関数(さいきかんすう)」を使った高度なレイヤー構造の平坦化(フラット化)を解説します。

ここをクリアすれば、CorelDRAW VBAのオブジェクト構造を完全に手中に収めたと言っても過言ではありません。さあ、一緒に本質を学んでいきましょう!

—

1. なぜ「ネスト構造」は実務の敵なのか?

CorelDRAWでデザイン業務を進めていると、データの再利用性を高めるために「グループ化」や「シンボル(Symbol)」を多用します。しかし、これが自動化プログラムにとっては大きな壁になります。

VBAでアクティブページの全図形を処理しようと `ActivePage.Shapes` をループさせても、グループやシンボルの「中身」までは自動で覗き見ることができません。
箱の中に箱が入っているような状態で、外側の箱だけを処理して「全部やった気になっていた」というバグは、CorelDRAW自動化あるあるの筆頭です。

解決の鍵:再帰関数(Recursive Function)とは?

自分自身を呼び出す関数のことです。
「グループを見つけたら、その中に入って同じ処理を繰り返す。さらにその中にグループがあれば、また中に入る……」という、まるで迷路を自動攻略するロジックを、驚くほど短いコードで実現できます。

—

2. 実装コード:ネストを完全分解し、フラットに再構築する

それでは、開発現場でそのままコピー&ペーストして使える実用コードを公開します。
このコードは、ドキュメント内のあらゆるグループとシンボルインスタンス(※必要に応じて展開)をくまなく探し出し、すべてのシェイプをページのルート(最上位)階層へ移動させ、最後に空になった殻のグループを削除する職人技のようなマクロです。

Sub FlattenAllShapes()
Dim doc As Document
Set doc = ActiveDocument

If doc Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical
Exit Sub
End If

‘ 処理の高速化と画面ちらつき防止
doc.BeginCommandGroup “レイヤーのフラット化”
EventsEnabled = False
Optimization = True

On Error GoTo ErrorHandler

‘ アクティブページの全シェイプに対して再帰処理を実行
‘ ※後ろからループを回すのが、オブジェクト移動時の鉄則です!
Dim i As Long
For i = ActivePage.Shapes.Count To 1 Step -1
ProcessShapeRecursively ActivePage.Shapes(i), Nothing
Anext:
Next i

MsgBox “フラット化処理が完了しました!”, vbInformation

ErrorHandler:
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End If

‘ 最適化の解除
Optimization = False
EventsEnabled = True
doc.EndCommandGroup
ActiveWindow.Refresh
End Sub

‘ — 【核心】再帰的にシェイプを走査し、フラット化するプロシージャ —
Private Sub ProcessShapeRecursively(sh As Shape, targetLayer As Layer)
Dim subSh As Shape
Dim i As Long

‘ 1. シンボルインスタンスの場合の処理(必要に応じて静的シェイプへ変換)
If sh.Type = cdrSymbolShape Then
‘ シンボルを通常のシェイプ群に変換してバラす場合
Set sh = sh.ConvertToCurves ‘ または .BreakApart (状況に応じて)
End If

‘ 2. グループシェイプの場合の処理
If sh.Type = cdrGroupShape Then
‘ グループ内のメンバーを先に再帰処理する
‘ グループの子供たちを外へ逃がすため、後ろからループ
For i = sh.Shapes.Count To 1 Step -1
Set subSh = sh.Shapes(i)

‘ 再帰呼び出し(さらにグループ内なら中に入る)
ProcessShapeRecursively subSh, targetLayer

‘ シェイプをページの最上位(ルート)へ移動
If targetLayer Is Nothing Then
subSh.MoveToLayer ActivePage.ActiveLayer
Else
subSh.MoveToLayer targetLayer
End If
Next i

‘ 中身が空っぽになった元のグループ殻を削除
sh.Delete

Else
‘ グループ以外の通常シェイプ(曲線、矩形、テキストなど)
‘ すでにルート層にあるものはそのまま、階層下にあれば移動
If Not sh.Layer Is ActivePage.ActiveLayer Then
If targetLayer Is Nothing Then
sh.MoveToLayer ActivePage.ActiveLayer
Else
sh.MoveToLayer targetLayer
End If
End If
End If
End Sub

—

3. コードの重要ポイントと、プロが教える「陥りやすい罠」

このコードには、CorelDRAW VBAを極めた者ならではの「現場の知恵」が詰まっています。いくつか重要なポイントを解説します。

① ループは必ず「後ろから(逆順)」回せ!

コレクション(`Shapes.Count To 1 Step -1`)を逆順で処理している点に注目してください。
もし前から順に(`1 To Count`)ループさせ、途中でシェイプを別のレイヤーへ移動させたり削除したりすると、インデックス番号がズレてしまい、「処理漏れ」や「実行時エラー(インデックスが範囲外です)」を引き起こします。
コレクションを操作・移動させる際は「後ろから」がVBAの鉄則です。

② `Optimization = True` の魔力

複雑なベクターデータを扱う際、CorelDRAWは画面の再描画(レンダリング)やイベント監視に膨大なリソースを割きます。
コードの冒頭で `Optimization = True` を宣言することで、これらを一時停止し、処理速度を劇的に向上させることができます。処理の最後には必ず `False` に戻すのを忘れないでくださいね。

③ シンボルインスタンスの扱いに注意

CorelDRAWの「シンボル」はマスターとインスタンスの関係にあります。インスタンスを無理やりバラすと予期せぬリンク切れを起こすことがあるため、実務データに合わせて `ConvertToCurves` や `BreakApart` の挙動は調整してください。

—

まとめ:ここをクリアすれば、もう怖くない!

今回は、少し応用的な「再帰関数」を使った複雑なグループ構造のフラット化について解説しました。

最初は「自分自身を呼び出す」という概念に少し頭がこんがらがるかもしれません。しかし、この仕組みを理解できると、どれほど複雑に入り組んだ他社製データであっても、一瞬で自分の扱いやすい形に自動整形できるようになります。

「マクロの記録」の向こう側にある、本当のプログラミングの面白さと効率化の爽快感を、ぜひあなたの開発現場で味わってみてください。
ここを乗り越えたあなたなら、どんなCorelDRAWの自動化案件も怖くありませんよ。応援しています!

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