【テクニカル・上級編】【中級者向け】ページ内の全シェイプを特定のレイヤーに自動振り分けする「レイヤー自動整理」ルーチン – Visio VBA解析バイブル

スポンサーリンク

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)」し、さらに高速化する手法について語ろうか。準備はできているか?

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