Visio VBAの深淵へ:Connection Pointsを完全制御し、動的コネクタ生成をマスターする
Visioの真価は「図形」そのものにあるのではない。図形同士を繋ぐ「メタデータと接続の連鎖」にある。
業務自動化の現場で、定型的なフローチャートやネットワーク図を自動生成する際、多くのエンジニアが躓くのが「接続点(Connection Points)」の動的制御だ。既製の図形に用意された接続点だけでは足りず、無理やりコネクタを繋いで図形が崩壊した経験はないだろうか?
今日は、`Shape.AddRow` を駆使し、プログラムから接続点を神の如く配置し、堅牢な自動結線を実現するアーキテクチャを伝授する。
—
1. なぜ「AddRow」の設計が重要なのか
Visioの `Section`(セクション)は、Excelのテーブルに近い構造をしている。特に `visSectionConnectionPts`(セクション番号: 7)へのアクセスは、図形のライフサイクルを直接操作する行為だ。
ここで犯しがちなミスは、「行のインデックスを固定値で決め打ちすること」だ。Visioの図形は、既存の接続点の削除や追加によってインデックスが変動する。これを考慮しないコードは、数ヶ月後に必ずバグる。
堅牢な設計のための3つの鉄則
1. インデックスではなく「行名」や「動的取得」を信じる: 行番号を直接指定してはならない。`AddRow` の戻り値である行インデックスを常に変数で保持せよ。
2. セクションの存在確認: 対象の図形に `visSectionConnectionPts` が存在しない場合、まずは `AddSection` で生成するという冗長性をコードに持たせること。
3. ロックとトランザクション: 多数の図形を操作する場合、`Application.ScreenUpdating` を制御し、処理の前後を `UndoScope` で囲むのがプロの作法だ。
—
2. プロダクションコード:接続点追加とコネクタ結線の自動化
以下のコードは、指定した図形の右側に接続点を追加し、そこに新しいコネクタを接続する実践的なモジュールだ。
Option Explicit
‘ 接続点を追加し、コネクタを接続するプロシージャ
Public Sub CreateDynamicConnection(targetShape As Visio.Shape, connectorType As String)
Dim vsoSection As Visio.Section
Dim rowIdx As Integer
Dim newConnector As Visio.Shape
‘ 1. Connection Points セクションが存在するか確認し、なければ追加
If Not targetShape.SectionExists(visSectionConnectionPts, 0) Then
targetShape.AddSection visSectionConnectionPts
End If
‘ 2. 新しい接続点を追加(行の末尾に追加)
‘ AddRowの戻り値は、追加された行のインデックス
rowIdx = targetShape.AddRow(visSectionConnectionPts, visRowLast, visTagDefault)
‘ 3. 座標の設定(XとYをミリメートル単位で指定)
‘ 注意: 図形のローカル座標系なので、中心を基準に設定する
targetShape.CellsSRC(visSectionConnectionPts, rowIdx, visCnnctX).FormulaU = “Width1”
targetShape.CellsSRC(visSectionConnectionPts, rowIdx, visCnnctY).FormulaU = “Height0.5”
‘ 4. コネクタを生成して接続
Set newConnector = ActivePage.DrawConnector(visConnectorStraight)
‘ 起点と終点を接続(BeginConnect / EndConnect を使用)
newConnector.CellsU(“BeginX”).GlueTo targetShape.CellsSRC(visSectionConnectionPts, rowIdx, visCnnctX)
Debug.Print “接続点追加成功: Row Index ” & rowIdx
End Sub
—
3. 現場でのトラブルを回避するための高度な知見
データベース連携の罠
データベース(ExcelやSQL Server)から読み込んだ座標をそのまま `FormulaU` に突っ込んではいけない。Visioは内部的に「インチ」を基準としていることが多い。常に `Application.ConvertResult` を使用し、単位変換をコード内で完結させること。
パフォーマンスの極意
数千個の図形をループで処理する場合、`Shape.AddRow` を繰り返すとVisioの再描画処理が走る。
- 解決策: 処理中は `Application.ScreenUpdating = False` にする。
- UndoScopeの活用: `BeginUndoScope` を使用することで、失敗時に一括でロールバック可能な状態を作り出す。これができるかどうかが、ツールとしての信頼性を分ける。
なぜ「GlueTo」を使うべきか
初心者は `PinX` や `PinY` を計算してコネクタを配置しようとする。これは愚策だ。`GlueTo` メソッドを使えば、図形を移動させた際にコネクタが追従する「インテリジェントな図面」が完成する。Visioのエンジンを信じろ。
—
結びに代えて:自動化は「設計」である
コードを書いて動かすことと、エンジニアリングをすることの間には巨大な壁がある。
`AddRow` を単なるメソッド呼び出しとして捉えるのではなく、「図形の構造を拡張し、データと視覚的関係を同期させるためのインターフェース」として定義し直してほしい。
このコードをベースに、君自身の業務に最適化された「コネクタ生成エンジン」を構築することを期待している。壁にぶつかったら、いつでも戻ってこい。Visioの神髄は、まだその先にあるのだから。
