Visioの混沌をコードで統べる:レイヤー自動整理による「構造的負債」の解消
Visio図面が巨大化する際、最も恐ろしいのは「カオス」だ。数千のシェイプがレイヤーという概念を無視して配置され、修正のたびに全シェイプを選択してプロパティを開く……そんな非効率な作業を繰り返すのは、エンジニアとして敗北を意味する。
今日は、Visio VBAの深淵に触れ、大規模図面の管理コストを劇的に下げる「レイヤー自動振り分けルーチン」を伝授する。これは単なるコードのコピペではない。オブジェクトのライフサイクルを制御し、メモリリークを許さない「アーキテクトのための防衛術」だ。
—
1. なぜ「手動」ではいけないのか:オブジェクト構造の理解
Visioの `Page` オブジェクトには `Layers` コレクションが存在する。レイヤーとは、単なる表示・非表示のスイッチではない。シェイプがどの `Layer` に所属しているかは、`LayerMember` セルを通じて管理される。
低品質なコードは、全シェイプに対してループを回す際、無駄なオブジェクト生成を繰り返し、Visioの描画エンジンに負荷をかけ続ける。我々が目指すのは、「最小のオーバーヘッドで、論理的に整合性の取れた状態へ遷移させる」ことだ。
—
2. レイヤー自動整理:実装の極意
以下のコードは、シェイプの `Master` や `Name` プロパティを判定し、動的にレイヤーへ割り当てる実装だ。
Option Explicit
‘ 伝説的な堅牢性を保つための定数管理
Private Const LAYER_NAME_INFRA As String = “Infrastructure”
Private Const LAYER_NAME_APP As String = “Application”
Public Sub AutoAssignLayers()
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim vsoLayer As Visio.Layer
Dim i As Long
‘ 画面描画の停止:パフォーマンス向上の定石
Application.ScreenUpdating = False
Set vsoPage = ActivePage
‘ ループ処理の最適化:コレクションのインデックスを直接叩く
For i = 1 To vsoPage.Shapes.Count
Set vsoShape = vsoPage.Shapes(i)
‘ カスタムプロパティやMaster名によるロジック判定
‘ ここを疎結合にするために、判定ロジックを関数化するのがプロの作法
If InStr(vsoShape.Name, “Server”) > 0 Then
Set vsoLayer = GetOrCreateLayer(vsoPage, LAYER_NAME_INFRA)
vsoLayer.Add vsoShape, 0
ElseIf InStr(vsoShape.Name, “Service”) > 0 Then
Set vsoLayer = GetOrCreateLayer(vsoPage, LAYER_NAME_APP)
vsoLayer.Add vsoShape, 0
End If
Next i
‘ オブジェクトの明示的解放:VBAのメモリ管理を過信してはならない
Set vsoLayer = Nothing
Set vsoShape = Nothing
Set vsoPage = Nothing
Application.ScreenUpdating = True
End Sub
‘ 既存レイヤーが存在しない場合に生成するファクトリーパターン
Private Function GetOrCreateLayer(page As Visio.Page, layerName As String) As Visio.Layer
Dim layer As Visio.Layer
On Error Resume Next
Set layer = page.Layers.Item(layerName)
If layer Is Nothing Then
Set layer = page.Layers.Add(layerName)
End If
On Error GoTo 0
Set GetOrCreateLayer = layer
End Function
—
3. チーフアーキテクトが教える「現場の最適化」
A. レガシー環境とWindows API
もし、図面の規模が数万シェイプを超える場合、VBA単体では処理落ちが発生する。その際は、`Win32 API` の `Sleep` を利用してCPU負荷を制御するか、あるいは `DoEvents` を適度に挟み、Visioが「応答なし」になるのを防ぐ必要がある。しかし、多用は禁物だ。あくまで処理のボトルネックを特定した後に適用せよ。
B. メモリリークという敵
VBAの参照カウンタは、循環参照や予期せぬエラー時にオブジェクトを保持し続けることがある。`Set = Nothing` はおまじないではない。エラーハンドラ内で `On Error Resume Next` を駆使し、異常終了時にも必ずオブジェクトを開放するガード節を組み込むのが、シニアエンジニアの嗜みだ。
C. システム連携の拡張性
今回はシェイプ名で判定したが、実務では `Shape.Cells(“Prop.SystemID”).ResultStr(“”)` のように、XMLからインポートした属性情報をキーにするのが一般的だ。これにより、外部DB(SQL Server等)とVisio図面を同期させる自動構成管理(CMDB)の一部として昇華できる。
—
最後に:エンジニアへの提言
レイヤー整理は、単なる見た目の問題ではない。それは「図面の複雑性をコードによって解決する」というエンジニアリングの本質に近い行為だ。Visioはレガシーなツールだと揶揄されることもあるが、そのオブジェクトモデルは極めて完成度が高い。
このコードをベースに、自社の業務プロセスに合わせた「自動化エンジン」を構築してほしい。管理コストがゼロに近づいたとき、君は本当の設計に時間を割くことができるようになるはずだ。
次は、これを「アドイン化(C#/.NET)」し、さらに高速化する手法について語ろうか。準備はできているか?
