こんにちは!CorelDRAW VBAの世界へようこそ。
マクロの記録ボタンを押して得られたコードを眺め、「なぜか動くけれど、狙った通りにならない…」と頭を抱えていませんか?
特に、デザインの現場で最もフラストレーションが溜まるポイントの一つが「オブジェクトの重なり順(Zオーダー)」です。前面に持ってきたいのに背面に隠れてしまう、グループ化された途端に順番が狂う――。
今回は、CorelDRAWのオブジェクトモデルにおける「重なり順」の正体を暴き、プログラムの力で完全にコントロールするための極意を伝授します。ここをクリアすれば、あなたのVBAスキルはマクロの記録者から「真の自動化エンジニア」へと大きく飛躍しますよ。それでは、一緒に紐解いていきましょう!
—
1. CorelDRAWの「重なり順」の正体を知る
まず大前提として、CorelDRAWの内部でオブジェクトがどのように管理されているかを知る必要があります。
人間が見ている画面上では「手前」と「奥」ですが、CorelDRAWのメモリ上(オブジェクトツリー)では、レイヤーの中にあるシェイプの「インデックス番号(何番目に生成・配置されたか)」として管理されています。
- 背面(一番最初に見えなくなる層): インデックスの若い方(通常 `1` や `First`)
- 前面(一番手前に表示される層): インデックスの老けた方(`Last` や `Shapes.Count`)
VBAでよく使われる `BringToFront` や `SendToBack` は、いわば「強制的にリストの一番最後(手前)へ移動させる」「一番最初(奥)へ移動させる」という力技の命令です。しかし、実際の業務では「特定の条件を満たすシェイプ同士で順序を並び替える」といった、より高度な制御が求められます。
—
2. 基本のメソッド:BringToFront と SendToBack
まずは基本のおさらいです。特定のシェイプを選択して手前や奥に送るコードを見てみましょう。
Sub BasicZOrderSample()
Dim s As Shape
‘ アクティブなドキュメントの選択している最初のシェイプを対象にする
If ActiveSelection.Shapes.Count > 0 Then
Set s = ActiveSelection.Shapes(1)
‘ 一番手前(最前面)に移動
s.BringToFront
‘ 【補足】一番奥に送りたい場合はこちら
‘ s.SendToBack
Else
MsgBox “シェイプが選択されていません。”, vbExclamation
End If
End Sub
ここで陥りやすい罠:複数選択時の挙動
もし複数のシェイプを選択して `BringToFront` を実行した場合、CorelDRAWは「選択された順番を保ったまま、まとめて最前面に移動」させます。しかし、意図した通りの相対的な重なり順にならないことが多いため、大量のオブジェクトを扱う実務では、この基本メソッド単体での制御には限界があります。
—
3. 実践アルゴリズム:属性に基づいて重なり順を完全支配する
ここからが本題です。
例えば、「赤い丸はすべて背面に、青い四角はすべてその手前に、文字は一番手前に配置し直す」というような自動整列処理を考えてみましょう。
実務で耐えうる、安全かつ高速な並び替えアルゴリズムのサンプルコードをプレゼントします。
Sub SortShapesByColorAndType()
Dim lr As Layer
Dim s As Shape
Dim i As Long
‘ 処理の高速化(画面描画とイベントを一時停止)
EventsEnabled = False
ActiveDocument.BeginCommandGroup “重なり順の自動整列”
On Error GoTo ErrorHandler
‘ アクティブレイヤーを取得
Set lr = ActiveLayer
If lr.Shapes.Count = 0 Then
MsgBox “レイヤーにシェイプが存在しません。”, vbInformation
GoTo ExitHandler
End If
‘ 【ステップ1】すべてのオブジェクトを一旦「一番奥」に沈める(基準を作る)
For Each s In lr.Shapes
s.SendToBack
Next s
‘ 【ステップ2】「四角形 (cdrRectShape)」をその上(前面)に積み上げる
For Each s In lr.Shapes
If s.Type = cdrRectShape Then
s.BringToFront
End If
Next s
‘ 【ステップ3】「楕円 (cdrEllipseShape)」をさらにその上(前面)に積み上げる
For Each s In lr.Shapes
If s.Type = cdrEllipseShape Then
s.BringToFront
End If
Next s
‘ 【ステップ4】最後に「テキスト (cdrTextShape)」を絶対的な最前面に配置する
For Each s In lr.Shapes
If s.Type = cdrTextShape Then
s.BringToFront
End If
Next s
MsgBox “オブジェクトの重なり順の再整列が完了しました!”, vbInformation
ErrorHandler:
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End If
ExitHandler:
‘ 処理の復元
ActiveDocument.EndCommandGroup
EventsEnabled = True
ActiveDocument.Window.Refresh
End Sub
コードのキモ:なぜこの書き方が「プロ仕様」なのか?
1. `EventsEnabled = False` と `BeginCommandGroup`
大量のシェイプを1つずつ `BringToFront` すると、その都度CorelDRAWが画面を再描画しようとするため、処理が耐えられないほど遅くなります。描画を止め、最後に `EndCommandGroup` でまとめることで、Ctrl+Z(元に戻す)が1回で済むスマートなコードになります。
2. 「いったん沈めてから、下から順に積み上げる」発想
カオスな状態から一瞬で秩序を生み出すには、「一度リセット(SendToBack)してから、優先度の低いものから順に BringToFront で上に重ねていく」という層構造(レイヤーサンドイッチ)のアルゴリズムが最強です。
—
4. ありがちなエラーと回避のテクニック
エラー①:「オブジェクトが削除されました(Object has been deleted)」
ループ処理の最中に `BringToFront` やシェイプの削除を行うと、インデックスの整合性が崩れてこのエラーを踏みがちです。今回は `For Each` を使って安全にコレクションを走査していますが、もしカウンター(`For i = 1 To Count`)を使う場合は、必ず後ろから数える(`For i = Count To 1 Step -1`)のがVBAの鉄則です。
エラー②:グループ化されたシェイプが無視される
グループ(`cdrGroupShape`)の中に踏み込んで順序を制御したい場合は、グループのメンバー(`s.Shapes`)に対して同様のアルゴリズムを再帰的(リカシブ)に適用する必要があります。まずは単体シェイプの制御をマスターしてから、グループへのアプローチに挑戦してみてください。
—
まとめ
CorelDRAW VBAにおけるオブジェクトの重なり順(Zオーダー)の支配、いかがでしたでしょうか?
「画面上の手前・奥」という感覚的な世界を、「インデックスの再構築とレイヤーサンドイッチのアルゴリズム」というエンジニアの視点で捉え直すことで、どんなに複雑なデザインデータであっても一瞬で美しく整頓できるようになります。
ここをクリアすれば、定型業務の自動化において怖いものはありません。ぜひ自分のデザイン環境に組み込んで、その圧倒的なスピード感を体感してください。それでは、次回の極限の知見でお会いしましょう!
