【テクニカル・上級編】Shape.StyleConnectedによるネットワーク線種の一括変更:接続関係を保持したままコネクタのスタイルを一括適用する手法 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを掌握する極限の知見:Shape.StyleConnectedによるネットワーク線種の一括変更と接続トポロジの死守

レガシーなインフラ設計図や、数千ノードに及ぶ大規模なネットワーク図の保守において、最も恐れられている作業何か。それは「配線の再接続」である。
元請けから「すべてのバックボーン回線を実線から破線に変更し、かつテーマカラーをスモークグレーに統一しろ」という非情な要件が降ってきたとき、無知なジュニアプログラマーはUIから一つずつコネクタを選択し、プロパティウィンドウをいじる。そして、わずかなマウスのズレにより接続(Glue)が外れ、背筋を凍らせるのだ。「どの図形とどの図形が繋がっていたか分からない」という破滅的なトポロジ崩壊の瞬間である。

我々シニアエンジニアにとって、Visioのオブジェクトモデルとは、単なるお絵描きキャンバスではない。厳密なグラフ理論に基づく「ノードとエッジの有向グラフ」である。
今回は、Visio VBAの深層において、コネクタの接続関係(Glue)を1ミリたりとも破壊することなく、スタイル・線種・テーマを一括適用する究極のテクニックを解説する。

1. Visioオブジェクトモデルの暗部:接続(Glue)とスタイルの乖離

Visioで「線」を描画する時、それは単なる `Shape` オブジェクトではない。端点が他の図形に吸着(Glue)された瞬間、その図形は空間座標の支配から解放され、「接続関係(Connection)」というメタデータに依存する動的エッジへと変貌する。

素人がやりがちな過ちは、以下のような全図形走査だ。

‘ 【アンチパターン】絶対にやってはならない愚行
Dim shp As Visio.Shape
For Each shp in ActivePage.Shapes
‘ スタイルを強制上書きすると、接続情報ごと初期化されるか、ルーティングが崩壊する
shp.Style = “MyCustomConnectorStyle”
Next shp

形状(Master)のスタイルを強引に適用すると、Visioの内部エンジン(VProceed)は図形のマスター定義を再適用しようとし、結果として既存のGlue(接続ピン)が強制解除される。数千本の配線が突然あらぬ方向を向き、宙ぶらりんになる悪夢の再現だ。

解決の鍵:`StyleConnected` プロパティとシェイプシートの直接制御

コネクタの接続を維持したまま外観のみを安全に書き換えるには、以下の2つのアプローチを使い分ける必要がある。
1. コネクタ(1Dシェイプ)のみを厳密にフィルタリングする
2. 既存の Glue を維持したまま、シェイプシート(ShapeSheet)のセル値、または安全なスタイルプロパティのみをインプレース更新する

2. 実装:接続トポロジを完全に保持する一括スタイル変更エンジン

以下に提供するコードは、単なるマクロではない。数百のドキュメントをバッチ処理するシステム管理者のための、メモリ最適化とエラーハンドリングを極限まで高めたプロダクション品質のVBAコードである。

Option Explicit

‘ ==============================================================================
‘ 処理名: ネットワーク図コネクタ一括スタイル変更エンジン
‘ 概要: 接続トポロジ(Glue)を完全保持したまま、1Dコネクタの線種・色を一括置換する
‘ ターゲット: Visio 2010 〜 2024 / Microsoft 365
‘ ==============================================================================
Public Sub ApplyNetworkConnectorStyleBatch()
‘ パフォーマンス最適化の極意:画面描画とイベントを完全に殺す
Dim origScreenUpdating As Boolean
Dim origEventFiring As Boolean

origScreenUpdating = Application.ScreenUpdating
origEventFiring = Application.EventList.Enabled

Application.ScreenUpdating = False
Application.EventList.Enabled = False

‘ エラーハンドリングによる確実な環境復元(メモリリーク・UIフリーズ防止)
On Error GoTo ErrorHandler

Dim doc As Visio.Document
Set doc = ActiveDocument

Dim page As Visio.Page
Set page = doc.ActivePage

Dim shp As Visio.Shape
Dim targetCount As Long
targetCount = 0

‘ トランザクションの開始(VisioのUndoスタックを1つにまとめ、処理速度を爆発的に上げる)
Dim undoScopeID As Long
undoScopeID = Application.BeginUndoScope(“ネットワークコネクタ一括スタイリング”)

‘ ページ内の全シェイプを走査
Dim i As Long
For i = page.Shapes.Count To 1 Step -1
Set shp = page.Shapes(i)

‘ 【重要】1Dシェイプ(コネクタ)であるか判定
‘ 2Dシェイプ(矩形や円)を誤って巻き込まないための厳密な型チェック
If shp.OneD = True Then

‘ 接続されている(=何らかの機器とGlueしている)コネクタに限定する場合のガード
‘ ※完全に孤立したコネクタも含める場合はこの条件を外す
If IsConnected(shp) Then

‘ スタイル適用のコアロジック
‘ 既存のGlueを破壊しないよう、LineColorとLinePatternのみを直接書き換える
‘ (Visioのスタイル名強制適用はコネクタの端点を狂わせるため避ける)

‘ 例: テーマカラーを「スモークグレー(RGB: 100, 100, 100)」に変更
shp.CellsSRC(visSectionObject, visRowLine, visLineColor).FormulaU = “RGB(100,100,100)”

‘ 例: 線種を「破線(Dash)」に変更 (Visioの標準パターン番号: 2 = 破線, 1 = 実線)
shp.CellsSRC(visSectionObject, visRowLine, visLinePattern).FormulaU = “2”

‘ 例: 線の太さを 1.5 pt に変更
shp.CellsSRC(visSectionObject, visRowLine, visLineWeight).FormulaU = “1.5 pt”

targetCount = targetCount + 1
End If
End If
Next i

‘ トランザクションの正常終了
Application.EndUndoScope undoScopeID, True

‘ 終了処理
Application.ScreenUpdating = origScreenUpdating
Application.EventList.Enabled = origEventFiring

MsgBox “処理完了: ” & targetCount & ” 本のネットワークコネクタのスタイルを、接続を維持したまま更新しました。”, vbInformation, “Visio Architect”
Exit Sub

ErrorHandler:
‘ 異常終了時の環境復元とメモリ解放
If undoScopeID <> 0 Then
Application.CancelUndoScope
End If
Application.ScreenUpdating = origScreenUpdating
Application.EventList.Enabled = origEventFiring

MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “System Error”
End Sub

‘ ==============================================================================
‘ 補助関数: コネクタが実際に何らかの図形と接続(Glue)されているか判定する
‘ ==============================================================================
Private Function IsConnected(ByVal shp As Visio.Shape) As Boolean
IsConnected = False

‘ 1Dシェイプの始点(BeginX)と終点(EndX)の接続情報を取得
Dim cellBegin As Visio.Cell
Dim cellEnd As Visio.Cell

On Error Resume Next
Set cellBegin = shp.Cells(“BeginX”)
Set cellEnd = shp.Cells(“EndX”)
On Error GoTo 0

If cellBegin Is Nothing Or cellEnd Is Nothing Then Exit Function

‘ 接続されている場合、Cells(… ).GlueShape などの兆候があるか、
‘ あるいは Shape.ConnectedShapes メソッドを使用する
Dim connectedFrom As Variant
Dim connectedTo As Variant

‘ 始点側が何らかのシェイプに接続されているか
connectedFrom = shp.ConnectedShapes(visConnectedShapesIncoming, “”)
‘ 終点側が何らかのシェイプに接続されているか
connectedTo = shp.ConnectedShapes(visConnectedShapesOutgoing, “”)

If UBound(connectedFrom) >= 0 Or UBound(connectedTo) >= 0 Then
IsConnected = True
End If
End Function

3. チーフアーキテクトが解説するコードの急所とパフォーマンス最適化

上記のコードには、単なる「動くコード」を超えた、エンタープライズ環境に耐えうる厳格な設計思想が組み込まれている。

① 画面描画とイベントの完全遮断 (`ScreenUpdating` / `EventList.Enabled`)

Visioは、1つのシェイプのプロパティを変更するたびに、画面の再描画(リペイント)とイベントリスナーの評価を行おうとする。数千本のコネクタを持つ図面でこれをやると、処理に数分〜数十分を要し、場合によってはメモリリークを引き起こす。
`ScreenUpdating = False` と `EventList.Enabled = False` を組み合わせることで、OSの描画リソースを完全にバイパスし、メモリ上で超高速なインメモリバッチ処理を実現している。

② Undoスコープのトランザクション管理

`BeginUndoScope` と `EndUndoScope` を用いることで、一連の変更をVisioの「単一の操作」として履歴に記録する。これにより、万が一意図しない結果になった場合でも、ユーザーはCtrl+Zの1回だけで元の完璧な状態にロールバックできる。プロフェッショナルなツールとは、常に「安全な逃げ道」が用意されているもののことだ。

③ シェイプシート直撃アプローチ (`CellsSRC`)

前述の通り、`Shape.Style` プロパティの書き換えはマスター定義の競合を引き起こす。
ここでは `CellsSRC`(Section, Row, Cellのインデックス指定)を用い、形状のマスター構造には一切触れず、描画属性を司るピンポイントのセル(LineColor, LinePatternなど)の数式(FormulaU)のみを書き換えている。これが、接続(Glue)を1ミリも狂わせないための最大の秘訣である。

4. レガシー環境・システム間連携への拡張

このVBAモジュールをさらに発展させれば、例えば外部のC# (VSTO) アプリケーションや、Web API経由で受け取ったJSON設定ファイルに基づき、Visio図面のインフラトポロジを動的に再スタイリングするエンタープライズ・パイプラインのコアエンジンとしても機能する。

企業のシステム管理において、図面は「ただの絵」ではなく「構成管理データベース(CMDB)の視覚的表現」である。
オブジェクトのライフサイクルを理解し、背後にある数理モデル(グラフ理論と接続トポロジ)を敬う者だけが、Visioを真に意のままに操ることができる。

静まり返ったサーバールームで、数千本の配線が一糸乱れず一瞬で新しいポリシーの色に染め上げられる瞬間――それこそが、コードによって物理世界を支配するエンジニアの醍醐味である。

タイトルとURLをコピーしました