Visio VBAの深淵を覗く:グループの「呪縛」を解き、絶対座標を掌握せよ
こんにちは。Visioのオートメーションの世界へようこそ。
「マクロの記録」で生成されたコードを動かしたとき、単体のシェイプなら完璧に動くのに、グループ化した途端に座標が狂い、絶望した経験はありませんか?
実は、Visioの座標系は「階層」という名の魔法にかかっています。グループやコンテナの中にあるシェイプにとって、その座標は親(グループ)からの「相対値」にすぎません。ページ全体から見た「絶対座標」を知るには、特別な呪文――`XYToPage`メソッドが必要です。
今日は、Visio開発の登竜門であり、かつ最大の難所である「座標の階層問題」を完全に攻略しましょう。
—
1. なぜ「Shape.Cells(“PinX”)」だけではダメなのか?
初学者が最初に陥る罠がこれです。
‘ 危険なコード:絶対座標のつもりで相対座標を拾っている
Debug.Print shp.Cells(“PinX”).ResultIU
Visioのシェイプには「ピン(回転軸)」という概念があり、その位置は常に「親」の座標系に依存します。
- ルート階層のシェイプ:ページ上の絶対座標
- グループ内のシェイプ:グループの左下を原点(0,0)とした相対座標
この違いを無視して座標を計算しようとすると、グループを移動させた瞬間にすべての計算が破綻します。ここに、`XYToPage`という救世主の出番がやってきます。
—
2. 魔法のメソッド「XYToPage」の正体
`XYToPage`メソッドは、「あるシェイプのローカル座標を、ページの絶対座標へと変換して返してくれる」という、まさに座標の翻訳機です。
このメソッドは、以下の3つの要素を引数に取ります。
1. ローカルX座標
2. ローカルY座標
3. 変換後の座標を格納する変数(参照渡し)
実践:グループ内のシェイプの絶対位置を特定する
以下のコードは、選択したシェイプがどこに埋もれていようとも、ページ上の正確な絶対座標(X, Y)を割り出すためのテンプレートです。
Sub GetAbsolutePosition()
Dim shp As Visio.Shape
Dim absX As Double, absY As Double
‘ 選択中のシェイプを取得
Set shp = ActiveWindow.Selection(1)
‘ シェイプの「ピン(中心点)」のローカル座標を基準に変換
‘ PinX, PinY をそのシェイプの親の座標系からページ座標系へ変換する
shp.XYToPage shp.Cells(“PinX”).ResultIU, _
shp.Cells(“PinY”).ResultIU, _
absX, absY
‘ 結果を出力
Debug.Print “絶対X座標: ” & absX & ” インチ”
Debug.Print “絶対Y座標: ” & absY & ” インチ”
End Sub
—
3. ここで躓くな!開発現場で頻出するエラーと対策
このコードを書いていて、以下のようなエラーや挙動に遭遇しませんか?
① 「オブジェクトがありません」エラー
もしシェイプを選択せずに実行すると、`ActiveWindow.Selection(1)` でエラーが出ます。
- 対策: 常に `If ActiveWindow.Selection.Count > 0 Then` でチェックする癖をつけましょう。
② インチ表記とミリメートル表記の混同
Visio内部の `ResultIU` は常に「インチ」です。もし「センチメートル」で扱いたい場合は、最後に `2.54` をかける必要があります。
- 知見: 単位変換で迷ったら、常に `ResultIU` で計算し、表示段階で変換するのがエンジニアの作法です。
—
4. チーフアーキテクトからのアドバイス
「グループの中にグループが入っている」という多重構造の場合でも、この `XYToPage` は自動的に再帰的に計算を行ってくれるため、非常に優秀です。
あなたが次に目指すべきステップは、この座標取得を応用して「自動配置エンジン」を作ることです。
- グループ内の特定のパーツを特定し、その絶対座標を計算する。
- その座標をもとに、別のシェイプを正確な位置に動的に配置する。
ここまでくれば、あなたはもう「マクロの記録」に頼る初心者ではありません。Visioの内部構造を理解した、真の自動化エンジニアです。
—
まとめ:Visioは「階層」がすべて
Visioの座標を支配することは、Visioのオブジェクトモデルを支配することと同義です。
「今の座標は、誰から見た座標なのか?」を常に自分に問いかけてください。
- Shape.Cells(“PinX/Y”):ローカル座標(親の都合)
- Shape.XYToPage:絶対座標(ページの真実)
この2つの使い分けができれば、どんなに複雑な図面であっても、あなたのプログラムは正確無比に動作します。さあ、次はあなたの業務フローを自動化する番ですよ。応援しています!
