Visio VBAの世界へようこそ!伝説のチーフアーキテクトとして、皆さんのVisio自動化への情熱を全力でサポートさせていただきます。
今回は、Visio VBAの基本中の基本でありながら、その奥深さに気づくと「Visioの真の力を引き出せる」と実感できるテーマに挑戦します。それは、図形間の「接続」を精密に解析することです。単に「図形Aと図形Bが繋がっている」という情報だけでなく、「Aのどの接続ポイントに、Bのどの接続ポイントが、どの方向で繋がっているのか」という、一歩踏み込んだ知見をVBAで抽出する方法を、丁寧に、そして深く掘り下げていきましょう。
ここをクリアすれば、Visio VBAの基本はバッチリですよ!
—
接続情報の詳細解析:Shape.ConnectsとConnectオブジェクトによる接続点・矢印方向の精密抽出
1. Visioの「接続」とは何か? その本質を見極める
Visioで図形を配置し、コネクタで繋ぐ。これはごく日常的な操作ですよね。しかし、この「接続」という行為の裏側には、Visioが持つ強力なオブジェクトモデルが隠されています。
一般的な図形描画ツールでは、線と図形は独立したオブジェクトとして扱われることが多いです。しかし、Visioのコネクタは違います。コネクタは、接続された図形との間に生きた関係性を築きます。図形を移動させればコネクタも追随し、図形を削除すればコネクタも消える。この賢い振る舞いこそが、Visioが「ダイアグラム作成ツール」として傑出している理由の一つです。
そして、この「生きた関係性」をVBAで完全に掌握するために必要なのが、`Shape.Connects`コレクションと、その中に含まれる`Connect`オブジェクトなのです。
2. Visio VBAの玄関口:オブジェクトモデルの階層を理解する
Visio VBAを扱う上で、まず理解すべきはオブジェクトの階層構造です。これは、Visioの「脳」と「体」の関係を把握するようなものです。
- Applicationオブジェクト: Visioアプリケーション全体を司る最上位のオブジェクト。Visioの起動から終了まで、あらゆる操作の起点となります。
- Documentオブジェクト: 現在開いているVisioファイル(.vsd, .vsdxなど)を表します。Applicationの下に複数存在しえます。
- Pageオブジェクト: Documentの中にある各ページ(描画ページ、背景ページなど)を表します。Documentの下に複数存在しえます。
- Shapeオブジェクト: Pageの中にある個々の図形(四角、丸、コネクタ、グループ図形など)を表します。Pageの下に無数に存在しえます。
今回の主役である「接続情報」は、特定の`Shape`オブジェクト(特にコネクタ)が持っている情報です。つまり、`Application` -> `Document` -> `Page` -> `Shape` とたどっていけば、目的の情報にたどり着けるわけです。
先輩エンジニアからのヒント: これらのオブジェクトは、それぞれが膨大なプロパティとメソッドを持っています。そして、これらのオブジェクトを効率的に操作することが、大規模なVisio自動化の鍵となります。無駄なオブジェクト生成やプロパティへのアクセスは、パフォーマンスを著しく低下させる可能性があります。常に「どのオブジェクトが、どんな情報を、どこに持っているか」を意識することが重要です。
3. ConnectsコレクションとConnectオブジェクトの深淵
さあ、いよいよ本丸です。図形間の接続情報を詳細に取得するためには、`Shape`オブジェクトが持つ`Connects`コレクションと、その中の一つ一つの`Connect`オブジェクトを理解することが不可欠です。
3.1. `Shape.Connects`コレクションとは?
`Shape.Connects`コレクションは、特定のShapeオブジェクト(特にコネクタ)が、他のどのShapeオブジェクトと、どのように接続されているかを示す`Connect`オブジェクトの集合体です。
少し分かりにくいかもしれませんね。ここで重要なのは、`Connects`コレクションは「コネクタ」だけでなく、「接続されている図形側」からも参照できるということです。
- コネクタの`Connects`コレクション: コネクタがどの図形と繋がっているか、その始点・終点両方の接続情報が格納されます。
- 図形(コネクタ以外)の`Connects`コレクション: その図形に接続しているコネクタの情報が格納されます。
今回は、特に「コネクタがどの図形に、どの接続点で、どの方向で繋がっているか」を解析したいので、コネクタである`Shape`オブジェクトの`Connects`コレクションに注目します。
3.2. `Connect`オブジェクトが保持する情報の種類
`Connect`オブジェクトは、一つ一つの「接続」の詳細を保持しています。これこそが、私たちが欲する精密な情報源です。
`Connect`オブジェクトの主なプロパティを見てみましょう。
- `FromShape`: 接続元のShapeオブジェクト。コネクタの場合、コネクタ自体を指します。
- `ToShape`: 接続先のShapeオブジェクト。コネクタが接続している図形(四角や丸など)を指します。
- `FromCell`: 接続元Shape(コネクタ)の、接続しているセルの情報。
- `ToCell`: 接続先Shape(図形)の、接続されているセルの情報。
- `FromPart`: 接続元Shape(コネクタ)の、どの部分が接続しているか(例: 始点、終点)。
- `ToPart`: 接続先Shape(図形)の、どの部分が接続されているか(例: 接続ポイント)。
- `Direction`: 接続の方向。コネクタの始点側が接続しているのか、終点側が接続しているのかを示します。
特に重要なのは`FromCell`、`ToCell`、`Direction`の3つです。
`FromCell`と`ToCell`は、単なる座標ではなく、Visioの内部セル名(`PinX`, `PinY`, `BeginX`, `EndX`など)を指します。これにより、「コネクタの始点が図形のどの接続ポイントに、あるいは図形のどの辺の中央に接続しているか」といった詳細な情報がわかるのです。
4. 実践!接続情報をVBAで抽出する
では、実際にVBAコードを書いて、選択したコネクタの接続情報を取得してみましょう。
シナリオ: Visioで適当な図形をいくつか配置し、コネクタで接続してください。そして、そのコネクタを選択した状態で以下のマクロを実行します。
Sub AnalyzeConnectorConnections()
Dim vsoApp As Visio.Application
Dim vsoDoc As Visio.Document
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim vsoConnect As Visio.Connect
Dim i As Integer ‘ Connectsコレクションのインデックス用
‘ 現在アクティブなVisioアプリケーションオブジェクトを取得
Set vsoApp = Visio.Application
‘ アクティブなドキュメントオブジェクトを取得
Set vsoDoc = vsoApp.ActiveDocument
‘ アクティブなページオブジェクトを取得
Set vsoPage = vsoApp.ActivePage
‘ 選択されているShapeオブジェクトがあるかチェック
If vsoApp.ActiveWindow.Selection.Count = 0 Then
MsgBox “コネクタを選択してください。”, vbExclamation
Exit Sub
End If
‘ 選択されているShapeオブジェクトを一つずつ処理
For Each vsoShape In vsoApp.ActiveWindow.Selection
‘ 選択されたShapeがコネクタ(1D図形)であるかを確認
‘ コネクタは基本的に1D図形であり、線形を保持します。
If vsoShape.OneD Then
Debug.Print “— 選択されたコネクタ: ” & vsoShape.NameID & ” (ID: ” & vsoShape.ID & “) —”
‘ コネクタのConnectsコレクションをループ
‘ Connectsコレクションには、コネクタが接続している両端の情報が含まれます
‘ 通常、コネクタは2つの図形に接続するので、Connectsコレクションには2つのConnectオブジェクトが含まれます
For i = 1 To vsoShape.Connects.Count
Set vsoConnect = vsoShape.Connects.Item(i) ‘ i番目のConnectオブジェクトを取得
‘ 接続先の図形名とID
Debug.Print ” 接続先図形: ” & vsoConnect.ToShape.NameID & ” (ID: ” & vsoConnect.ToShape.ID & “)”
‘ 接続元のコネクタ側の接続点情報
‘ Connect.FromCellは、コネクタ自身のどのセルが接続しているかを示す
Debug.Print ” コネクタ側接続セル: ” & vsoConnect.FromCell.Name
‘ Connect.FromPartは、コネクタのどの部分が接続しているかを示す(例: 始点, 終点)
Debug.Print ” コネクタ側接続部分: ” & GetConnectPartName(vsoConnect.FromPart)
‘ 接続先の図形側の接続点情報
‘ Connect.ToCellは、接続先図形のどのセルが接続されているかを示す
Debug.Print ” 図形側接続セル: ” & vsoConnect.ToCell.Name
‘ Connect.ToPartは、接続先図形のどの部分が接続されているかを示す(例: 接続点)
Debug.Print ” 図形側接続部分: ” & GetConnectPartName(vsoConnect.ToPart)
‘ 接続の方向(コネクタの始点側か終点側か)
Debug.Print ” 接続方向: ” & GetConnectDirectionName(vsoConnect.Direction)
Debug.Print “” ‘ 区切り
Next i
Else
Debug.Print “選択された図形 ‘” & vsoShape.NameID & “‘ はコネクタではありません。”
End If
Next vsoShape
‘ オブジェクトの解放(メモリ管理の観点から重要)
Set vsoConnect = Nothing
Set vsoShape = Nothing
Set vsoPage = Nothing
Set vsoDoc = Nothing
Set vsoApp = Nothing
End Sub
‘ Connect.FromPart / Connect.ToPart の値を分かりやすい文字列に変換するヘルパー関数
Function GetConnectPartName(partValue As Visio.VisConnectParts) As String
Select Case partValue
Case visConnectFromError: GetConnectPartName = “エラー”
Case visConnectFromBegin: GetConnectPartName = “コネクタ始点”
Case visConnectFromEnd: GetConnectPartName = “コネクタ終点”
Case visConnectFromMidpoint: GetConnectPartName = “コネクタ中点”
Case visConnectToError: GetConnectPartName = “エラー”
Case visConnectToPart: GetConnectPartName = “図形の接続点”
Case visConnectToCell: GetConnectPartName = “図形内のセル”
Case visConnectToAPoint: GetConnectPartName = “図形上の任意の点”
Case visConnectToIX: GetConnectPartName = “図形上のX座標”
Case visConnectToIY: GetConnectPartName = “図形上のY座標”
Case Else: GetConnectPartName = “不明 (” & partValue & “)”
End Select
End Function
‘ Connect.Direction の値を分かりやすい文字列に変換するヘルパー関数
Function GetConnectDirectionName(directionValue As Visio.VisConnectDirs) As String
Select Case directionValue
Case visConnectDirBegin: GetConnectDirectionName = “コネクタの始点側”
Case visConnectDirEnd: GetConnectDirectionName = “コネクタの終点側”
Case visConnectDirNone: GetConnectDirectionName = “方向なし”
Case Else: GetConnectDirectionName = “不明 (” & directionValue & “)”
End Select
End Function
5. コード解説と陥りやすい罠
上記のコードは、選択されたコネクタの接続情報を取得し、イミディエイトウィンドウに表示します。一つずつポイントを見ていきましょう。
5.1. オブジェクトの取得と循環参照の回避
Set vsoApp = Visio.Application
Set vsoDoc = vsoApp.ActiveDocument
Set vsoPage = vsoApp.ActivePage
これはVisio VBAの基本中の基本です。しかし、オブジェクトの参照は適切に行い、不要になったら必ず`Set obj = Nothing`で解放することが重要です。特に、大規模な図面や多くのループ処理を行う場合、解放を怠るとメモリリークやパフォーマンス低下の原因となります。VBAでは自動ガベージコレクションが機能しますが、明示的な解放は堅牢なコードの証です。
5.2. コネクタの特定 (`Shape.OneD`プロパティ)
If vsoShape.OneD Then
‘ … 処理 …
Else
Debug.Print “選択された図形 ‘” & vsoShape.NameID & “‘ はコネクタではありません。”
End If
Visioの図形には、1次元(OneD)図形と2次元(TwoD)図形があります。コネクタは線として扱われるため、`Shape.OneD`プロパティが`True`になります。これにより、選択された図形がコネクタであるかどうかを判別できます。
陥りやすい罠: マクロの記録で生成されたコードには、選択図形を無条件に扱うものが多いです。しかし、実際の自動化では「対象の図形が本当にコネクタなのか?」「複数選択されていないか?」などを常にチェックする堅牢性が必要です。
5.3. `Connects`コレクションのループ
For i = 1 To vsoShape.Connects.Count
Set vsoConnect = vsoShape.Connects.Item(i)
‘ … 接続情報の取得 …
Next i
コネクタは通常、2つの図形(始点側と終点側)に接続しているので、`Connects.Count`は`2`になることが多いです。このループで、コネクタの各接続先に関する`Connect`オブジェクトを一つずつ取得しています。
5.4. `Connect`オブジェクトのプロパティ詳細
- `vsoConnect.ToShape.NameID` / `vsoConnect.ToShape.ID`:
接続先の図形を特定するためのプロパティです。`NameID`はVisioが内部的に持つ一意の名前で、`ID`はページ内で一意の数値IDです。これらはデバッグや特定の図形をプログラムで識別する際に非常に役立ちます。
- `vsoConnect.FromCell.Name`:
これはコネクタ自身のShapeSheetにおけるセル名を返します。例えば、`BeginX`や`EndX`といった文字列が返ってきます。これは「コネクタの始点が、コネクタ自身のどのXY座標セルから伸びているか」を示します。
- `vsoConnect.ToCell.Name`:
これが今回最も注目すべきポイントの一つです。これは接続先の図形のShapeSheetにおけるセル名を返します。例えば、`Connections.X1`(最初の接続ポイントのX座標)、`Connections.X2`(2番目の接続ポイントのX座標)、あるいは図形の辺の中点を示す`PinX`や`PinY`などが返ってきます。
これにより、「図形のどの接続ポイントに、あるいはどの辺にコネクタが接続しているか」を精密に特定できます。
先輩エンジニアからの深い洞察: `FromCell`や`ToCell`は単なる文字列ではありません。これらはVisioの内部データベースであるShapeSheetにおける「セルの名前」そのものです。この名前を使って、後で`vsoConnect.ToShape.Cells(vsoConnect.ToCell.Name).Result(“mm”)`のようにアクセスすれば、その接続点の座標値などを直接取得することも可能です。Visioの内部構造を理解する上で非常に重要な概念です。
- `vsoConnect.FromPart` / `vsoConnect.ToPart`:
これらのプロパティは、接続が「コネクタの始点側からか終点側からか」、あるいは「図形の接続ポイントに接続しているか、それとも図形の内部セルに接続しているか」といった、より抽象的な接続の種類を示します。ヘルパー関数`GetConnectPartName`で具体的な意味を解説しています。
- `vsoConnect.Direction`:
これは、`Connect`オブジェクトが示す接続が、コネクタの「始点側」に相当するのか、「終点側」に相当するのかを示します。ヘルパー関数`GetConnectDirectionName`で具体的な意味を解説しています。
例えば、コネクタAが図形Bと図形Cに接続している場合、`Connects`コレクションには2つの`Connect`オブジェクトがあります。
一つは`Direction = visConnectDirBegin`で、コネクタAの始点が図形Bに接続していることを示します。
もう一つは`Direction = visConnectDirEnd`で、コネクタAの終点が図形Cに接続していることを示します。
この情報があることで、コネクタの「どの端」が「どの図形」に繋がっているのかを明確に区別できるのです。
6. さらに深く!矢印方向と接続点の解析
`Direction`プロパティと`ToCell.Name`は、単なる接続の有無を超えた、Visioのインテリジェンスの核心に迫る情報です。
例えば、あるコネクタの`Direction`が`visConnectDirBegin`で、`ToCell.Name`が`Connections.X2`だったとしましょう。これは、「コネクタの始点側が、接続先図形の2番目の接続ポイントに結合している」ことを意味します。
もし`ToCell.Name`が`PinX`や`PinY`だった場合、それは「図形の中点や回転の中心に接続している」ことになります。また、`BeginX`や`EndX`であれば「図形の端点に接続している」ことを示します。
これらの詳細な情報を使えば、以下のような高度な自動化が可能になります。
- 接続点ベースの検証: 「特定の図形は必ず特定の接続ポイントに接続されていなければならない」といったビジネスルールをVBAで検証する。
- 自動レイアウトの最適化: 接続点の位置に応じて図形を整列させたり、コネクタのルーティングを調整したりする。
- データ連携の強化: 接続点の情報を基に、外部システムへより詳細なダイアグラム構造データを出力する。
7. まとめ
今回は、Visio VBAにおいて図形間の「接続」情報を精密に解析する方法を学びました。
- `Application` -> `Document` -> `Page` -> `Shape` のオブジェクト階層をたどり、コネクタである`Shape`オブジェクトにアクセスする。
- コネクタの`Shape.Connects`コレクションから、個々の`Connect`オブジェクトを取得する。
- `Connect`オブジェクトが持つ`ToShape`、`FromCell`、`ToCell`、`Direction`といったプロパティを駆使して、接続元・接続先の図形、接続ポイントのセル名、そして接続の方向を詳細に抽出する。
これらの知見は、単なるマクロの記録から一歩も二歩も踏み出し、Visioの真の力を引き出すための強力な武器となります。最初は少し難しく感じるかもしれませんが、Visioの内部構造への理解が深まれば深まるほど、皆さんの自動化スキルは飛躍的に向上します。
大丈夫、一歩ずつ進んでいきましょう!この知識を応用して、皆さんのVisio自動化の可能性を広げていってください。Visio VBAの旅は、まだ始まったばかりです!
