CorelDRAW VBAの深淵:動的ドキュメント変換とオブジェクトライフサイクルの極意
CorelDRAWのオートメーションにおいて、最も「死」に近い作業は、ドキュメントのページサイズを動的に変更し、その中で漂う無秩序なオブジェクト群を再配置することだ。
多くの初学者は `Page.SetSize` を呼んで満足する。しかし、シニアエンジニアであれば理解しているはずだ。CorelDRAWのオブジェクトモデルは、単なる階層構造ではない。それは、メモリ上に展開された膨大な座標系と、Undoスタックという名の「負債」の塊である。
今回は、実務で遭遇する「急なサイズ変更要求」に対し、メモリを汚さず、かつ数学的整合性を保って全オブジェクトを再配置する手法を解説する。
—
1. オブジェクトモデルの盲点:なぜ「全選択」してはいけないのか
VBAで全オブジェクトを操作しようとするとき、`ActivePage.Shapes.All` を多用していないだろうか?
これは大規模なドキュメントではメモリリークとパフォーマンス低下の元凶となる。
真のアーキテクトは、`Layer` オブジェクトをトラバースし、各シェイプの参照を明示的に取得・解放する。CorelDRAWのVBAインターフェースはCOM経由であるため、参照の放置はGC(ガベージコレクション)を阻害し、長時間稼働するバッチ処理においてアプリケーションをクラッシュさせる。
—
2. 実装:動的ページリサイズと余白アジャストのコアロジック
以下に、メモリ効率を考慮した「ページサイズ変更&センタリング」のエンジニアリングサンプルを示す。
‘ 伝説的なチーフアーキテクトによる、クリーンなリサイズルーチン
Public Sub AdjustDocumentLayout(ByVal newW As Double, ByVal newH As Double, ByVal margin As Double)
Dim doc As Document
Dim p As Page
Dim layer As Layer
Dim s As Shape
Dim allShapes As ShapeRange
Set doc = ActiveDocument
Set p = doc.ActivePage
‘ 1. Undoスタックを管理し、処理の重さを可視化する
Optimization = True
doc.BeginCommandGroup “Dynamic Resizing”
‘ 2. ページサイズ変更
p.SetSize newW, newH
‘ 3. 全レイヤーを走査してShapeRangeを構築
‘ 直接ループせず、Rangeを生成してから一度に操作するのが高速化の定石
Set allShapes = p.Shapes.All
‘ 4. コンテンツのセンタリングとリサイズ(アスペクト比維持)
‘ 座標計算はすべてDocument単位で行う(インチ/ミリの混同を防ぐため)
With allShapes
.SetPosition (newW / 2), (newH / 2)
‘ ここで必要に応じて .SetSize を呼び出し、マージン計算を反映させる
End With
‘ 5. 明示的なメモリ解放と最適化の終了
Set allShapes = Nothing
doc.EndCommandGroup
Optimization = False
doc.ActiveWindow.Refresh
Debug.Print “Layout adjustment completed successfully.”
End Sub
—
3. シニアエンジニアが知るべき「見えない制約」
座標系の数学的整合性
CorelDRAWの原点(0,0)はデフォルトで左下だが、`SetSize` を行うと基準点がずれることがある。特に、デザインがページ中央からずれている場合、`allShapes.SetPosition` を行う前に、現在のバウンディングボックスの重心を取得し、ターゲットサイズとの差分をオフセットとして適用しなければならない。単純な計算では、複雑なグループ化オブジェクトが崩壊する可能性がある。
Undoスタックの爆発を防ぐ
`Optimization = True` は単なる高速化フラグではない。これはCorelDRAWの内部レンダリングエンジンに対して、「一連の操作を単一のトランザクションとして扱え」と命じるものだ。これを行わないと、サイズ変更の過程で発生する無数の描画イベントがWindows APIのメッセージキューを埋め尽くし、UIのフリーズを招く。
レガシー環境との共存(Win32 APIの活用)
もし、CorelDRAWのウィンドウハンドルを取得し、外部システムからメッセージを送信して自動化を完了させたい場合、`FindWindow` や `PostMessage` を `User32.dll` から呼び出す必要がある。
その際、`ByVal` での文字列渡しには細心の注意を払え。VBAの文字列はBSTRであるため、アンマネージドコードとの境界でメモリ破壊が起きやすい。必ず `StrPtr` を経由したポインタ操作を検討すべきだ。
—
結論:コードは「機能」ではなく「仕組み」として書け
今回提示したコードは、単にページサイズを変えるだけのものではない。
ドキュメントのライフサイクルを制御し、メモリの消費を最適化し、将来の修正に耐えうる「仕組み」である。
CorelDRAW VBAにおいて、最も重要なのは「描画」ではなく「管理」だ。次にこのスクリプトを触るエンジニアが、元の設計思想を瞬時に理解できるよう、コードには常に「なぜそうしたのか」という意図をコメントとして刻み込め。
それが、伝説的な自動化エンジニアの流儀である。
