Visioの座標地獄を脱出せよ:`XYToPage`で解き明かす絶対座標の真実
Visioでの自動化において、最も多くのエンジニアが挫折し、そして最も多くのバグを生み出す領域。それが「座標計算」だ。
「グループ化した瞬間に、子シェイプの座標が狂った」
「コンテナに入れた途端、位置情報が親からの相対値になって制御不能になった」
こんな経験はないだろうか。`Shape.Cells(“PinX”)`や`PinY`を直接参照して位置を制御しようとするのは、初心者が陥る典型的な罠だ。Visioにおいて、シェイプの座標は「親のコンテキスト」に依存する。この本質を理解せず、場当たり的な計算で凌いでいる限り、複雑な図面を扱うツールは一生完成しない。
今日は、Visioのオブジェクトモデルを掌握し、グループやコンテナの階層を超えて「ページ上の絶対座標」を確実に射抜くための極限の解法を伝授する。
—
1. なぜ「PinX/PinY」の直接参照が地雷なのか
Visioのシェイプには「ローカル座標系」と「ページ座標系」がある。
グループ化やコンテナへの追加を行うと、そのシェイプの`PinX`/`PinY`は「親シェイプの基準点からの相対値」へと再定義される。
つまり、階層が深くなればなるほど、`PinX`の値は「ページ上のどこにあるか」という情報とは無関係な数値へと変貌する。これを解決せずに「絶対位置」を操作しようとすれば、計算式は階層の数だけ複雑化し、メンテナンス不可能なスパゲッティコードが完成する。
ここで登場するのが、Visioが提供する唯一の正解、`XYToPage`メソッドだ。
—
2. 実装の極意:XYToPageによる座標抽出アルゴリズム
`XYToPage`は、シェイプのローカル座標系における一点を、ページ座標系(インチ単位のダブル型)へ変換するメソッドだ。これを使えば、階層構造を意識することなく、「今、ページ上のどこにいるか」という真実のみを取得できる。
本番環境で通用するプロダクションコード
以下のコードは、選択したシェイプがどこに埋もれていようと、その絶対位置(ページ上の座標)を正確に取得するモジュールだ。
Option Explicit
‘ @brief 指定シェイプのページ上の絶対座標を取得する
‘ @param shp 対象のシェイプ
‘ @param x ページ上のX座標(戻り値)
‘ @param y ページ上のY座標(戻り値)
Public Sub GetAbsolutePosition(ByVal shp As Visio.Shape, ByRef x As Double, ByRef y As Double)
‘ 念のためのエラーハンドリング:シェイプが有効か確認
If shp Is Nothing Then Exit Sub
‘ 重要: PinX/PinYは中心点。左下を基準にしたい場合はローカル座標を調整する必要がある
‘ ここではシェイプのピン位置(通常は中心)をページ座標に変換する
shp.XYToPage 0, 0, x, y
‘ 【重要】XYToPageはインチ単位で値を返す。
‘ 日本の業務環境ではmm単位での制御が必要なケースが多いため、必要に応じて変換する
‘ x = x 25.4
‘ y = y 25.4
End Sub
‘ 実行例:選択中のシェイプの絶対座標をイミディエイトウィンドウに出力
Public Sub DebugPrintAbsolutePosition()
Dim shp As Visio.Shape
Dim absX As Double, absY As Double
If ActiveWindow.Selection.Count = 0 Then Exit Sub
Set shp = ActiveWindow.Selection(1)
Call GetAbsolutePosition(shp, absX, absY)
Debug.Print “Shape Name: ” & shp.Name
Debug.Print “Absolute Position (Page): X=” & absX & “, Y=” & absY
End Sub
—
3. 堅牢な設計のための3つの鉄則
現場で使い捨てのツールを作って終わらせるのではなく、長期運用に耐えるシステムを構築するために、以下の設計指針を遵守せよ。
① 座標単位の統一(インチ vs ミリ)
Visio内部の座標系は常に「インチ」だ。画面上でミリ表示にしていても、VBAが扱うのはインチである。計算ミスを防ぐため、「すべての座標操作は内部的にインチで行い、ユーザーインターフェースや設定ファイルとの境界でのみミリに変換する」という設計ルールを徹底すること。
② データベース・外部ファイル連携の罠
絶対座標を外部DBに記録する場合、注意が必要だ。ページサイズが変われば相対的な位置関係は変わる可能性がある。DBに保存すべきは「絶対座標」だけでなく、「どのページのどのグループに所属しているか」という階層IDもあわせて格納することを推奨する。
③ 再帰的な再配置の回避
もし「絶対座標を指定してシェイプを移動させる」必要がある場合は、`XYToPage`の逆を行わねばならない。だが、それは非常に難易度が高い。基本的には「移動はグループ単位で行う」か「一度グループから外に出して座標を書き換え、再グループ化する」というアプローチの方が、バグの発生確率は圧倒的に低い。
—
最後に:エンジニアとしての矜持
Visioの自動化において、コードの綺麗さは「オブジェクトの特性をどれだけ理解しているか」に比例する。
`XYToPage`を使いこなすということは、Visioという巨大な座標系の迷宮から抜け出すための鍵を手に入れたということだ。このメソッドを理解した今、君はもはや「階層」という名の壁に怯える必要はない。
次にVisioを開くときは、ただコードを書くのではない。Visioのオブジェクトモデルが設計者として何を意図したのかを考え、その意図に沿った堅牢なツールを組み上げてほしい。
それが、世界最高峰の自動化エンジニアへの第一歩だ。
