Visio VBA深淵:Connectオブジェクトが語る接続点の座標と方向性、堅牢設計の要諦
諸君、Visio VBAの世界へようこそ。単なる図形描画ツールの域を超え、ビジネスプロセスやシステムアーキテクチャの根幹を視覚化するVisio。しかし、その真の力を引き出すには、表面的な操作に留まらず、オブジェクトモデルの深淵を理解する必要がある。
特に、図形間の「接続」はVisioの骨格を成す要素であり、これを正確に、そして詳細に解析する能力は、業務効率化ツール開発において極めて重要だ。本稿では、`Shape.Connects`コレクションと`Connect`オブジェクトを徹底的に解剖し、単なる「つながり」では終わらない、「どの接続ポイント(X/Yセル)に」「どの方向で」コネクタが結合しているかを精密に抽出する極限の知見を伝授する。一般的なリファレンスには決して載らない、現場でバグに泣かされぬための堅牢な設計思想、そしてパフォーマンスと保守性を両立するプロダクションコード例とともに、諸君のVisio VBAスキルを一段上のレベルへと引き上げよう。
—
なぜ接続情報の詳細解析が不可欠なのか?
Visioの図面は情報システムである。図形はエンティティ、コネクタはリレーションシップを表現する。だが、「AとBが繋がっている」という情報だけでは、多くのビジネス要件を満たせない。
- データフローの方向性: データがAからBへ流れるのか、BからAへ流れるのか。あるいは双方向なのか。
- 物理的な接続点: どのポートにケーブルが挿さっているのか。論理的な接続ポート名と物理的な座標。
- 接続点の意味: その接続は図形の中心点に吸着しているのか、特定の端点(開始点/終了点)なのか、それともエッジ上の任意の点なのか。
これらの情報は、単なる図面表示を超え、以下のような高度な自動化を実現するために不可欠となる。
- 設定ファイルの自動生成: ネットワーク図からルータのポート設定を自動生成。
- 整合性チェック: データベースER図と実際のDBスキーマの整合性チェック。
- 影響分析: 特定のコンポーネントが変更された場合、どの関連コンポーネントに影響があるか。
- レポート生成: 接続情報を集計し、Excelやデータベースに出力する。
諸君が開発するツールが、こうした真の価値を提供するためには、`Connect`オブジェクトの深い理解は避けて通れない道なのだ。
—
基礎の再定義:Connectオブジェクトの解剖
`Shape.Connects`コレクションは、特定の図形(`Shape`オブジェクト)に接続しているすべての`Connect`オブジェクトの集合である。この`Connect`オブジェクトこそが、接続情報の真髄を握っている。
`Connect`オブジェクトは、主に以下のプロパティを持つ。
- `FromSheet`: コネクタの始点側が接続している図形(`Shape`オブジェクト)。
- `ToSheet`: コネクタの終点側が接続している図形(`Shape`オブジェクト)。
- `FromCell`: コネクタの始点側が接続している、`FromSheet`内のShapeSheetセル名(例: `”Connections.X1″`)。
- `ToCell`: コネクタの終点側が接続している、`ToSheet`内のShapeSheetセル名(例: `”Connections.Y1″`)。
- `FromPart`: コネクタの始点側が`FromSheet`のどの部分に接続しているかを示す列挙型(`Visio.VisCellVals`)。
- `ToPart`: コネクタの終点側が`ToSheet`のどの部分に接続しているかを示す列挙型(`Visio.VisCellVals`)。
ここで注目すべきは、`FromCell`と`ToCell`が文字列であるという事実だ。これは単なる文字列ではない。これは、Visioが図形の内部構造、すなわちShapeSheetにおける特定の接続ポイントを指し示すための「パス」なのだ。そして`FromPart`と`ToPart`は、その接続が図形全体に対する相対的などの「部分」で行われているかを示す、極めて重要なヒントである。
—
「接続点」の真実:ShapeSheetとFromCell/ToCellの関連
`FromCell`や`ToCell`が`”Connections.X1″`や`”Connections.Y1″`のような文字列を返すとき、それは接続先の図形(`FromSheet`または`ToSheet`)のShapeSheetにある`Connections`セクションの特定の行、特定のセルを指している。
例えば、`Connect.FromCell`が`”Connections.X1″`を返した場合、それはコネクタの始点が、接続先の図形(`Connect.FromSheet`)の`Connections`セクションの1行目にあるX方向の接続ポイントに結合していることを意味する。
真の接続座標を取得する手順は以下のようになる。
1. `Connect.FromSheet` (または `ToSheet`) から接続先の図形オブジェクトを取得。
2. その図形オブジェクトの`CellsU(Connect.FromCell)` (または `Connect.ToCell`) メソッドを使って、該当するShapeSheetセルオブジェクトを取得。
3. 取得したセルオブジェクトの`Result(visCentimeters)` (または他の単位) を使って、接続点の物理的な座標値を取得。
これは、単にコネクタの`BeginX`/`EndX`セルを見るだけでは得られない、接続先図形から見た正確な接続点を特定するための唯一無二の方法だ。
FromPart/ToPartが語る接続点の種類
`FromPart`と`ToPart`プロパティは、接続先の図形における接続点の「タイプ」を示す。これらの値は、`Visio.VisCellVals`列挙型で定義されており、非常に示唆に富む。
- `visConnectFromBeginX` (1): 図形の左端 (X座標の開始点)
- `visConnectFromEndX` (2): 図形の右端 (X座標の終了点)
- `visConnectFromBeginY` (3): 図形の下端 (Y座標の開始点)
- `visConnectFromEndY` (4): 図形の上端 (Y座標の終了点)
- `visConnectFromMidpoint` (5): 図形の中心点
- `visConnectFromEdge` (6): 図形の端(エッジ)上の任意の点(特に固定された接続ポイントではない場合)
- `visConnectFromVertex` (7): 図形の頂点(Geometryセクションの特定の点)
- `visConnectFromNone` (0): 接続ポイントが特定できない、または接続されていない。
これらの値を解析することで、「このコネクタは、この図形の右端に繋がっている」といった、よりセマンティックな情報を抽出できるようになる。これは、単なるX/Y座標だけでは表現できない、設計意図の解析に役立つ。
—
「矢印方向」の精密抽出:コネクタの向きとFrom/To
コネクタの方向性は、`Connect`オブジェクトの`FromSheet`と`ToSheet`プロパティが示す通り、コネクタの始点が`FromSheet`に、終点が`ToSheet`に接続していることを意味する。しかし、視覚的な矢印の有無は、コネクタ自身のShapeSheetセルで制御されている。
- `BeginArrow`セル: コネクタの始点側の矢印スタイル。0は矢印なし。
- `EndArrow`セル: コネクタの終点側の矢印スタイル。0は矢印なし。
これらのセルの値を組み合わせることで、コネクタの論理的な方向性と、視覚的な矢印の方向性を完全に把握できる。
1. 単方向(`FromSheet` → `ToSheet`): `BeginArrow`が0で、`EndArrow`が0以外。
2. 単方向(`ToSheet` → `FromSheet`): `BeginArrow`が0以外で、`EndArrow`が0。
3. 双方向: `BeginArrow`も`EndArrow`も0以外。
4. 無方向: `BeginArrow`も`EndArrow`も0。
このロジックを実装することで、データフローや依存関係の真の方向性をシステムが理解できるようになる。
—
堅牢な実装のための設計原則
さて、概念は理解できたとして、これを実務で利用するツールに落とし込むには、いくつかの設計原則を厳守する必要がある。諸君が書くコードは、単に動けばよいというものではない。未来の自分、あるいは同僚が、安心して保守・拡張できるものでなければならない。
1. エラーハンドリングの徹底
Visioの図面は千差万別であり、ユーザーの操作は予測不能だ。常に異常系を想定せよ。
- 図形が見つからない: `Application.ActivePage.Shapes.ItemU`などで図形を取得する際は、存在しない名前やIDを指定するとエラーになる。
- コネクタがない: `Shape.Connects`コレクションが空の場合がある。
- ShapeSheetセルが見つからない: カスタムプロパティや特定のセクションが存在しない場合がある。`Shape.CellsU`メソッドはエラーを発生させる可能性がある。
- オブジェクト参照の無効化: `Set obj = Nothing` の後にアクセスするとエラー。
`On Error GoTo` を適切に使い、具体的なエラーメッセージをログに出力するか、ユーザーに分かりやすい形で通知すべきだ。
2. パフォーマンスへの配慮
大規模なVisio図面を扱う場合、パフォーマンスは致命的な問題となり得る。
- `Application.ScreenUpdating = False`: 処理中にVisioの画面更新を停止させることで、大幅な速度向上を図れる。処理終了後に忘れずに`True`に戻すこと。
- オブジェクト参照の最小化: ループ内で同じオブジェクトを何度も取得したり、不必要なプロパティアクセスを繰り返したりしない。一度取得したオブジェクトは変数に格納して再利用する。
- 早期解放: 不要になったオブジェクト参照は、`Set obj = Nothing` で明示的に解放する。特に大規模なループ内では、メモリリークやパフォーマンス低下の原因となり得る。
3. 保守性と可読性の追求
プロダクションコードは「物語」である。読み手がその意図を容易に理解できなければならない。
- マジックストリングの回避: `Connections.X1`のようなShapeSheetセル名をコード内に直接記述するのではなく、定数として定義するか、列挙型を活用する。Visioのバージョンアップでセル名が変わる可能性は低いが、定数化はコードの意図を明確にする。
- ロジックの分離: 複雑な処理は、複数の関数やサブルーチンに分割する。特に、接続情報を取得する部分、解析する部分、出力する部分など。
- データ構造の活用: 取得した接続情報は、単にデバッグウィンドウに出力するだけでなく、カスタムクラスやユーザー定義型(UDT)に格納して構造化する。これにより、後続の処理で扱いやすくなり、可読性も向上する。
4. ファイル/データベース連携の注意点
Visio図面から抽出した情報を外部システムと連携させる場合、VisioのオブジェクトIDに関する深い理解が不可欠だ。
- `Shape.ID`の罠: `Shape.ID`はVisioアプリケーションのセッション内で一意である。しかし、図面を保存して再度開くと、同じ図形であっても`ID`が変わる可能性がある。これは、データベースの外部キーとして使用するには非常に危険だ。
- 永続的な識別子の利用:
- `Shape.NameU`: 図形名(ユニバーサル名)。通常は図形を識別するのに適しているが、ユーザーが変更する可能性がある。
- カスタムプロパティ (`Shape.CellsU(“Prop.MyCustomID”)`): 図形に独自の識別子を付与し、それをデータベースの主キーや外部キーとして利用するのが最も堅牢な方法だ。Visioのプロパティウィンドウから設定するか、VBAで自動的に付与できる。
- 一意なハッシュ値: 図形のGeometryデータなどからハッシュ値を生成し、それを識別子とする方法もあるが、複雑性が増す。
データベーススキーマを設計する際は、上記の点を考慮し、`Shape.ID`を直接保存するのではなく、`NameU`やカスタムプロパティ、あるいはその両方を組み合わせた識別子を保存することを強く推奨する。
—
実践コード:接続情報の詳細解析ユーティリティ
それでは、上記の原則に基づいた堅牢で保守性の高いコードを見ていこう。ここでは、選択された図形、またはページ上のすべての図形について、その接続情報を詳細に解析し、構造化されたデータとして抽出するVBAコードを提供する。
まず、接続情報を格納するためのクラスモジュールをプロジェクトに追加する(名前は`ConnectionDetail`とする)。
クラスモジュール: `ConnectionDetail`
.net
‘ クラス名: ConnectionDetail
‘ 目的: Visioの単一の接続に関する詳細情報を保持する
Option Explicit
Public FromShapeID As Long ‘ 始点側図形のVisio ID (セッション内)
Public FromShapeNameU As String ‘ 始点側図形のユニバーサル名
Public FromCellName As String ‘ 始点側が接続しているShapeSheetセル名 (例: “Connections.X1”)
Public FromPartType As Visio.VisCellVals ‘ 始点側接続点のタイプ (例: visConnectFromEndX)
Public FromX As Double ‘ 始点側接続点のX座標 (ページ座標)
Public FromY As Double ‘ 始点側接続点のY座標 (ページ座標)
Public ToShapeID As Long ‘ 終点側図形のVisio ID (セッション内)
Public ToShapeNameU As String ‘ 終点側図形のユニバーサル名
Public ToCellName As String ‘ 終点側が接続しているShapeSheetセル名 (例: “Connections.Y1”)
Public ToPartType As Visio.VisCellVals ‘ 終点側接続点のタイプ (例: visConnectFromBeginX)
Public ToX As Double ‘ 終点側接続点のX座標 (ページ座標)
Public ToY As Double ‘ 終点側接続点のY座標 (ページ座標)
Public ConnectorID As Long ‘ コネクタ図形のVisio ID (セッション内)
Public ConnectorNameU As String ‘ コネクタ図形のユニバーサル名
Public Direction As String ‘ 接続の方向性 (“FromTo”, “ToFrom”, “TwoWay”, “NoArrow”)
‘ オプション: 接続点に関する追加情報 (例: 論理ポート名など)
Public Function GetDescription() As String
GetDescription = “Connector(” & Me.ConnectorNameU & “) [” & Me.ConnectorID & “] connects ” & _
“From: ” & Me.FromShapeNameU & ” [” & Me.FromShapeID & “] at ” & Me.FromCellName & ” (” & Me.FromPartType & “) ” & _
“To: ” & Me.ToShapeNameU & ” [” & Me.ToShapeID & “] at ” & Me.ToCellName & ” (” & Me.ToPartType & “) ” & _
“Direction: ” & Me.Direction
End Function
次に、このクラスを使って接続情報を解析する標準モジュールコード。
標準モジュール: `Module1`
.net
‘ 標準モジュール: Module1
Option Explicit
‘ ShapeSheetセル名の定数定義 (保守性向上)
Private Const CELL_BEGIN_ARROW As String = “BeginArrow”
Private Const CELL_END_ARROW As String = “EndArrow”
”’
”’ ConnectionDetailオブジェクトのリストとして返します。
”’
”’ 解析対象の単一図形。Nothingの場合はアクティブページ内のコネクタ全てを対象。
”’
Public Function AnalyzeShapeConnections(Optional ByVal targetShape As Visio.Shape = Nothing) As Collection
Dim collConnections As New Collection
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape ‘ コネクタ図形を指す
Dim vsoConnect As Visio.Connect
Dim clsConnDetail As ConnectionDetail
Dim vsoFromShape As Visio.Shape
Dim vsoToShape As Visio.Shape
Dim dblFromX As Double, dblFromY As Double
Dim dblToX As Double, dblToY As Double
Dim beginArrowVal As Double
Dim endArrowVal As Double
Dim strDirection As String
‘ パフォーマンス向上のため画面更新を停止
Application.ScreenUpdating = False
Application.ShowChanges = False ‘ Visio 2013以降のLive Preview対策
On Error GoTo ErrorHandler
Set vsoPage = Application.ActivePage
‘ 解析対象のコネクタを取得
Dim shapesToProcess As Visio.Shapes
If Not targetShape Is Nothing Then
‘ 特定の図形が渡された場合、その図形がコネクタでなければ処理をスキップ
If targetShape.OneD Then
Set shapesToProcess = Application.CreateCustomCollection(targetShape)
Else
Debug.Print “指定された図形はコネクタではありません。コネクタの接続情報のみ解析します。”
Set AnalyzeShapeConnections = collConnections
GoTo CleanExit
End If
Else
‘ targetShapeがNothingの場合、アクティブページ内の全コネクタを取得
Set shapesToProcess = vsoPage.Shapes
End If
For Each vsoShape In shapesToProcess
‘ コネクタ図形のみを対象とする
If vsoShape.OneD Then ‘ OneDプロパティがTrueならコネクタ
‘ Shape.Connectsコレクションは、その図形に「繋がっている」ものを返す。
‘ コネクタの場合、通常はConnects.Countは0か、自分自身に繋がっている場合など。
‘ コネクタの接続情報は、コネクタ自身のBeginX/YがFromShapeに、EndX/YがToShapeに繋がっている情報を見るべき。
‘ しかし、Connectsコレクションは両端の情報を持つため、ここではその両端を対象とする。
If vsoShape.Connects.Count > 0 Then
For Each vsoConnect In vsoShape.Connects
‘ Connectオブジェクトは、コネクタの「端」と「接続先の図形」の関係を表す。
‘ vsoConnect.FromSheet がコネクタの始点側の接続先図形
‘ vsoConnect.ToSheet がコネクタの終点側の接続先図形
Set clsConnDetail = New ConnectionDetail
‘ コネクタ自身の情報
clsConnDetail.ConnectorID = vsoShape.ID
clsConnDetail.ConnectorNameU = vsoShape.NameU
‘ 始点側の接続情報
Set vsoFromShape = vsoConnect.FromSheet
If Not vsoFromShape Is Nothing Then
clsConnDetail.FromShapeID = vsoFromShape.ID
clsConnDetail.FromShapeNameU = vsoFromShape.NameU
clsConnDetail.FromCellName = vsoConnect.FromCell
clsConnDetail.FromPartType = vsoConnect.FromPart
‘ 接続点の実際の座標を取得 (FromCellをShapeSheetセルとして参照)
If vsoFromShape.CellsU.ItemExists(vsoConnect.FromCell, visExistsAnywhere) Then
‘ 接続先の図形から見た接続点の座標を変換して取得
‘ vsoFromShape.CellsU(vsoConnect.FromCell) は Connections.X1 など
‘ そのX1セルをFromShapeのローカル座標からページ座標に変換
dblFromX = vsoFromShape.CellsU(vsoConnect.FromCell).Result(visCentimeters)
dblFromY = vsoFromShape.CellsU(Replace(vsoConnect.FromCell, “X”, “Y”), visExistsAnywhere).Result(visCentimeters)
‘ 注: Connections.X1/Y1 は通常ペアで存在する。FromCellがXならYを推測。
‘ 図形のローカル座標からページ座標への変換
Dim arrFromCoords(0 To 1) As Double
arrFromCoords(0) = dblFromX
arrFromCoords(1) = dblFromY
vsoFromShape.TransformPoints arrFromCoords, visXFormPrepToPage
clsConnDetail.FromX = arrFromCoords(0)
clsConnDetail.FromY = arrFromCoords(1)
Else
Debug.Print “Warning: FromShape (” & vsoFromShape.NameU & “) does not have cell ‘” & vsoConnect.FromCell & “‘.”
End If
End If
‘ 終点側の接続情報
Set vsoToShape = vsoConnect.ToSheet
If Not vsoToShape Is Nothing Then
clsConnDetail.ToShapeID = vsoToShape.ID
clsConnDetail.ToShapeNameU = vsoToShape.NameU
clsConnDetail.ToCellName = vsoConnect.ToCell
clsConnDetail.ToPartType = vsoConnect.ToPart
‘ 接続点の実際の座標を取得 (ToCellをShapeSheetセルとして参照)
If vsoToShape.CellsU.ItemExists(vsoConnect.ToCell, visExistsAnywhere) Then
dblToX = vsoToShape.CellsU(vsoConnect.ToCell).Result(visCentimeters)
dblToY = vsoToShape.CellsU(Replace(vsoConnect.ToCell, “X”, “Y”), visExistsAnywhere).Result(visCentimeters)
Dim arrToCoords(0 To 1) As Double
arrToCoords(0) = dblToX
arrToCoords(1) = dblToY
vsoToShape.TransformPoints arrToCoords, visXFormPrepToPage
clsConnDetail.ToX = arrToCoords(0)
clsConnDetail.ToY = arrToCoords(1)
Else
Debug.Print “Warning: ToShape (” & vsoToShape.NameU & “) does not have cell ‘” & vsoConnect.ToCell & “‘.”
End If
End If
‘ 矢印の方向性を判定
beginArrowVal = vsoShape.CellsU(CELL_BEGIN_ARROW).Result(visNoCast)
endArrowVal = vsoShape.CellsU(CELL_END_ARROW).Result(visNoCast)
If beginArrowVal > 0 And endArrowVal > 0 Then
strDirection = “TwoWay”
ElseIf beginArrowVal > 0 Then
strDirection = “ToFrom” ‘ コネクタの始点に矢印があれば、ToSheetからFromSheetへの方向
ElseIf endArrowVal > 0 Then
strDirection = “FromTo” ‘ コネクタの終点に矢印があれば、FromSheetからToSheetへの方向
Else
strDirection = “NoArrow”
End If
clsConnDetail.Direction = strDirection
collConnections.Add clsConnDetail
‘ オブジェクト参照の早期解放
Set clsConnDetail = Nothing
Set vsoFromShape = Nothing
Set vsoToShape = Nothing
Next vsoConnect
End If
End If
Next vsoShape
Set AnalyzeShapeConnections = collConnections
CleanExit:
‘ 画面更新を元に戻す
Application.ScreenUpdating = True
Application.ShowChanges = True
Exit Function
ErrorHandler:
Debug.Print “エラー発生: ” & Err.Number & ” – ” & Err.Description
Resume CleanExit
End Function
”’
”’
Public Sub ExtractAllPageConnections()
Dim collResults As Collection
Dim clsConnDetail As ConnectionDetail
‘ アクティブページ内の全コネクタを解析
Set collResults = AnalyzeShapeConnections(Nothing)
If collResults.Count > 0 Then
Debug.Print “— Visio Connection Analysis Results —”
For Each clsConnDetail In collResults
Debug.Print clsConnDetail.GetDescription()
Debug.Print ” From Coords (Page): (” & clsConnDetail.FromX & “, ” & clsConnDetail.FromY & “)”
Debug.Print ” To Coords (Page): (” & clsConnDetail.ToX & “, ” & clsConnDetail.ToY & “)”
Debug.Print “—————————————”
Next clsConnDetail
Else
Debug.Print “アクティブページにコネクタが見つかりませんでした。”
End If
Set collResults = Nothing
End Sub
”’
”’
Public Sub ExtractSelectedShapeConnections()
Dim vsoSelection As Visio.Selection
Dim vsoSelectedShape As Visio.Shape
Dim collResults As Collection
Dim clsConnDetail As ConnectionDetail
On Error GoTo ErrorHandler
Set vsoSelection = Application.ActiveWindow.Selection
If vsoSelection.Count = 0 Then
MsgBox “コネクタを選択してください。”, vbExclamation
Exit Sub
ElseIf vsoSelection.Count > 1 Then
MsgBox “複数のコネクタが選択されています。最初のコネクタのみ解析します。”, vbInformation
Set vsoSelectedShape = vsoSelection.Item(1)
Else
Set vsoSelectedShape = vsoSelection.Item(1)
End If
‘ 選択された図形がコネクタであることを確認
If Not vsoSelectedShape.OneD Then
MsgBox “選択された図形はコネクタではありません。コネクタを選択してください。”, vbExclamation
Exit Sub
End If
Set collResults = AnalyzeShapeConnections(vsoSelectedShape)
If collResults.Count > 0 Then
Debug.Print “— Selected Shape Connection Analysis Results —”
For Each clsConnDetail In collResults
Debug.Print clsConnDetail.GetDescription()
Debug.Print ” From Coords (Page): (” & clsConnDetail.FromX & “, ” & clsConnDetail.FromY & “)”
Debug.Print ” To Coords (Page): (” & clsConnDetail.ToX & “, ” & clsConnDetail.ToY & “)”
Debug.Print “—————————————”
Next clsConnDetail
Else
Debug.Print “選択されたコネクタには有効な接続情報が見つかりませんでした。”
End If
Set collResults = Nothing
Set vsoSelectedShape = Nothing
Set vsoSelection = Nothing
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
コード解説と「なぜこの書き方なのか」
1. `ConnectionDetail`クラスモジュール:
- 抽出した情報を構造化して保持するために、カスタムクラスを導入した。これは、単に複数の配列や辞書を使うよりも、データの意味を明確にし、後続の処理で扱いやすく、保守性を劇的に向上させる。
- 各プロパティは、`Connect`オブジェクトから得られる情報と、ShapeSheetから追加で抽出した情報(座標、方向性)をマッピングしている。
- `GetDescription`メソッドは、クラス自体が自身の情報表現を持つことで、デバッグやロギングを容易にする。
2. `AnalyzeShapeConnections`関数:
- `Application.ScreenUpdating = False` / `Application.ShowChanges = False`: 大量の図形を処理する際のパフォーマンスチューニングの要諦。画面描画は重い処理であり、これを抑制することで処理速度が大幅に向上する。処理の最後で必ず`True`に戻すことを忘れてはならない。
- `On Error GoTo ErrorHandler`: 堅牢なコードには必須。図形やセルが存在しない場合など、様々なエラーケースに対応できるようにしている。
- `targetShape`引数: 単一の図形だけでなく、ページ全体のコネクタを処理できるよう、柔軟なインターフェースを提供。`Nothing`チェックで分岐。
- `vsoShape.OneD`: 図形が1次元(コネクタ)であるかを判別する最も確実な方法。これにより、不要な図形(2次元図形)の処理をスキップし、効率を高める。
- `Shape.Connects`コレクションのイテレーション: ここが接続情報の核心。`vsoConnect`オブジェクトを通して、コネクタの各端がどの図形に、どのセル名で接続しているかを抽出する。
- `FromCell`/`ToCell`の利用:
- `clsConnDetail.FromCellName = vsoConnect.FromCell` で、接続先のShapeSheetセル名(例: `”Connections.X1″`)を文字列として保存。
- `vsoFromShape.CellsU(vsoConnect.FromCell).Result(visCentimeters)` で、そのセルが持つ実際の値(接続点の座標値)を取得する。`visCentimeters`は、単位変換をVisioに任せるためのベストプラクティス。
- `Replace(vsoConnect.FromCell, “X”, “Y”)`: `Connections.X1`のようなX座標セルから、対応するY座標セル(`Connections.Y1`)を推測して取得するテクニック。これはVisioのShapeSheet構造を深く理解しているからこそ可能な、洗練されたアプローチだ。
- `TransformPoints`メソッド: `CellsU(“Connections.X1”).Result`などで取得される座標は、多くの場合、接続先の図形のローカル座標系における値である。これをVisioページのグローバル座標系に変換するために`TransformPoints`を使用する。これにより、複数の図形の接続点を比較する際などに、統一された座標系で扱えるようになる。これが「精密抽出」の重要な一歩だ。
- `FromPartType`の保存: `visConnectFromEndX`のような列挙型を直接保存することで、接続点のセマンティックな意味を保持し、後続処理での判断材料とする。
- 矢印方向の判定: `BeginArrow`と`EndArrow`セルの値を直接参照し、その値によってコネクタの方向性を論理的に判定する。これは単なる視覚情報だけでなく、ビジネスルールにおけるデータフローの方向性を示す重要な指標となる。
- オブジェクト参照の早期解放 (`Set obj = Nothing`): ループ内で生成された`ConnectionDetail`インスタンスや、一時的に使用した`Shape`オブジェクト参照は、メモリを効率的に管理するために明示的に解放する。これは特に大規模な図面でメモリ消費を抑え、パフォーマンスを安定させるために重要だ。
3. `ExtractAllPageConnections` / `ExtractSelectedShapeConnections`プロシージャ:
- ユーザーが実行しやすいように、ページ全体を対象とするものと、選択図形を対象とするものを分離。
- `Debug.Print`で結果を出力しているが、実務ではこれをCSVファイル出力、Excelシートへの書き出し、あるいはデータベースへのインサート処理などに置き換えることになる。その際、`ConnectionDetail`クラスのリストがあることで、非常に簡単にデータを処理できるだろう。
—
まとめと次のステップ
諸君、本稿で伝授した`Connect`オブジェクトとShapeSheetセルの連携、そして`FromPart`/`ToPart`の解析、さらには堅牢な設計原則とプロダクションコード例は、Visio VBAによる業務自動化を一段上のレベルへと引き上げるための基盤となる。
単なる「つながり」の情報を超え、「どこに」「どのように」「どの方向で」繋がっているかを精密に抽出する能力は、諸君が開発するツールに、より深い知性と実用性をもたらすだろう。
この知識を武器に、諸君はVisio図面から以下のような高度な自動化を実現できるはずだ。
- 複雑なネットワーク構成図から、ルーティングテーブルやファイアウォール設定を自動生成する。
- ER図から、テーブル間の参照整合性制約を自動的に検証する。
- プロセスフロー図から、ボトルネックとなる結合点を特定し、改善案を提示する。
さあ、この「極限の知見」を手に、Visio VBAの真の力を解き放ち、諸君の業務プロセスを革新せよ!未来の自動化は、諸君の深い洞察と堅牢なコードから生まれるのだ。
