CorelDRAW VBAの「死の淵」を避ける:ページ操作における動的インデックス管理の鉄則
CorelDRAWの自動化において、最も初歩的かつ最も多くの事故を引き起こすのが「ページコレクションの操作」だ。特にテンプレートからページを増殖させ、不要な空ページを削除するようなフローでは、甘い実装は即座に`Runtime Error 91`や`Out of Range`を招く。
なぜ、素人の書いたループは崩壊するのか?
答えは単純だ。「動的に変化するコレクションのインデックスを、順方向(1 to N)で走査しているから」に他ならない。
今日は、数千ページ規模のドキュメントを平然と処理するアーキテクトの視点から、「絶対に壊れないページ操作」の極意を伝授する。
—
1. なぜ「順方向ループ」は地獄を見るのか
初心者が陥る典型的なアンチパターンを見てみよう。
‘ 【避けるべきアンチパターン】
For i = 1 To ActiveDocument.Pages.Count
If ActiveDocument.Pages(i).Shapes.Count = 0 Then
ActiveDocument.Pages(i).Delete ‘ ページを削除すると後続のインデックスが前方にシフトする!
End If
Next i
このコードを実行した瞬間、CorelDRAWは混乱する。`i=1`を削除したとき、元々`i=2`だったページが`i=1`に繰り上がる。しかしループカウンターは`i=2`に進んでしまうため、元々2ページ目だったページが処理からスキップされるのだ。最悪の場合、インデックス範囲外を参照してプロセスがクラッシュする。
2. プロフェッショナルの解:逆方向走査(Reverse Traversal)
動的なコレクション操作の鉄則は、「後ろから処理せよ」である。末尾を削除しても、それより前のインデックスには一切影響が及ばない。これが、スタックやリスト構造を扱う際の基本にして最強の防御策だ。
安全なページ削除のプロダクションコード
Sub SafeCleanupPages()
Dim doc As Document
Dim i As Long
Set doc = ActiveDocument
‘ 最低1ページは残すというビジネスロジックを考慮
If doc.Pages.Count <= 1 Then Exit Sub
' 逆方向ループ:インデックスの整合性を完全に守る
For i = doc.Pages.Count To 1 Step -1
' ページに何もない場合のみ削除(実務ではここに複雑な条件が入る)
If doc.Pages(i).Shapes.Count = 0 Then
' 最後のページ以外は削除可能、といった制限もここでかける
If doc.Pages(i).Index <> 1 Then
doc.Pages(i).Delete
End If
End If
Next i
End Sub
—
3. 動的生成における「参照の安定化」
次に、テンプレートからのページ増殖について。単に`ActiveDocument.AddPages`を繰り返すのは危険だ。特に外部データ(CSVやJSON)と同期させる場合、「現在のページ状態」と「データセットの同期」を切り離す設計が重要になる。
堅牢なページ追加の設計パターン
1. 初期化: 必要な数だけ先にページを確保する。
2. 同期: ページオブジェクトを配列やコレクションに格納し、直接操作する。
Sub GeneratePagesFromData(count As Integer)
Dim i As Integer
Dim p As Page
‘ ページ追加時は末尾に追加される性質を利用し、参照を確保する
For i = 1 To count
Set p = ActiveDocument.AddPages(1)
p.Name = “AutoPage_” & i
‘ 外部データとの連携:ここでオブジェクトに情報を書き込む
‘ p.Layers(“Layer 1”).CreateArtisticText …
Next i
End Sub
—
4. 現場で生き残るための「3つの戒律」
大規模プロジェクトを統括する中で、私がメンバーに厳守させているルールだ。
1. オブジェクトのキャッシュを信じるな: `ActiveDocument`や`ActivePage`を頻繁に参照するのはコストが高い。ループの冒頭で変数にセットし、その変数を使い回せ。
2. エラーハンドリングは「逃げ」ではない: ページ削除直前には必ず`On Error Resume Next`を使い、想定外のロックや保護ページに対処せよ。ただし、処理後は必ず`On Error GoTo 0`で正常系に戻すこと。
3. トランザクションを意識せよ: ページ操作は「取り消し(Undo)」コストが非常に重い。複雑な編集を行う際は、`doc.BeginCommandGroup “MassPageUpdate”`で囲み、処理の塊を1つのUndo単位として管理せよ。
最後に
CorelDRAWのVBAは、一見すると古臭い言語に見えるかもしれない。しかし、その裏側にあるオブジェクトモデルの深淵を理解すれば、これほど強力な自動化ツールはない。
「なんとなく動いた」から「構造的に壊れない」コードへ。
あなたが書くその1行が、明日、同僚の数時間を救うことになる。コードに魂を込めろ。それがプロフェッショナルだ。
