Visioのページ管理を「地獄」から解放せよ:Page.Index操作の極意
大規模な構成図やシステム設計書をVisioで管理しているエンジニア諸君。ページ数が50を超えたあたりで、「ページ順序の整理」という名の徒労に時間を溶かしてはいないだろうか?
GUIでドラッグ&ドロップを繰り返すのは、エンジニアの仕事ではない。今回は、Visioのオブジェクトモデルを掌握し、ページ順序をルールに基づき一瞬で最適化する「Page Index Automator」の極限実装を伝授する。
1. なぜVisioのページ並べ替えは「壊れやすい」のか?
Visioの `Page.Index` は、単なるプロパティではない。「現在のドキュメント内の相対位置」を示す動的なインデックスだ。
多くの初心者が陥る罠は、ループ内で `Page(i).Index = target` のように直接代入しようとすることだ。これは、インデックスを変更した瞬間に他のページのインデックスも再計算されるため、ループの整合性が崩壊し、予期せぬ順序になるか、あるいはランダムアクセスエラーで落ちる。
真の解決策:
「並べ替えたい順序を配列(またはコレクション)に格納し、その順序通りに `Page.Reorder` メソッドを一度だけ(あるいは適切に)呼び出す」こと。これが、Visioのメモリモデルを汚染しない唯一の正解だ。
2. プロダクションコード:Page Organizer
以下のコードは、ページ名に含まれるプレフィックス(例: `01_Overview`, `02_Network`…)を抽出し、昇順で全ページを再配置する実務用スクリプトだ。
Option Explicit
‘ ———————————————————
‘ @brief ページを名前順に自動ソートする
‘ @author Chief Architect
‘ ———————————————————
Public Sub SortPagesByName()
Dim vsoDoc As Document
Set vsoDoc = ActiveDocument
Dim vsoPages As Pages
Set vsoPages = vsoDoc.Pages
Dim i As Long
Dim pageCount As Long
pageCount = vsoPages.Count
‘ ページ情報を格納する配列(IDと名前をペアで保持)
‘ ※IndexではなくIDで管理するのが生存戦略の基本
Dim pageInfo() As Variant
ReDim pageInfo(1 To pageCount, 1 To 2)
For i = 1 To pageCount
pageInfo(i, 1) = vsoPages.Item(i).ID
pageInfo(i, 2) = vsoPages.Item(i).Name
Next i
‘ バブルソートによる名前順整列
‘ 大規模な場合はクイックソート等に差し替えること
Call SortArray(pageInfo)
‘ ページを順序通りにReorder
‘ VisioのReorderは1から始まるインデックスで指定
For i = 1 To pageCount
‘ IDを指定して現在の位置から目的のインデックスへ移動
‘ ※インデックス1から順に配置していくことで整合性を保つ
vsoDoc.Pages.ItemFromID(pageInfo(i, 1)).Index = i
Next i
MsgBox “ページ整理が完了しました。”, vbInformation
End Sub
‘ シンプルな2次元配列のソート用ヘルパー
Private Sub SortArray(ByRef arr() As Variant)
Dim i As Long, j As Long
Dim tempID As Long, tempName As String
For i = LBound(arr, 1) To UBound(arr, 1) – 1
For j = i + 1 To UBound(arr, 1)
If StrComp(arr(i, 2), arr(j, 2), vbTextCompare) > 0 Then
tempID = arr(i, 1): tempName = arr(i, 2)
arr(i, 1) = arr(j, 1): arr(i, 2) = arr(j, 2)
arr(j, 1) = tempID: arr(j, 2) = tempName
End If
Next j
Next i
End Sub
3. この設計が「堅牢」である理由
1. IndexではなくIDを基準にする: `Page.Index` は変動する不安定な値だが、`Page.ID` はオブジェクトが削除されるまで不変だ。処理の途中でインデックスがずれても、IDさえ把握していれば確実にターゲットを捕まえられる。
2. 疎結合な処理: ソートロジック(`SortArray`)とVisio操作(`SortPagesByName`)を分離している。将来的に「名前順」ではなく「作成日順」や「カスタムプロパティ順」にルールを変更したい場合、ソートロジックを差し替えるだけで対応可能だ。
3. エラーハンドリングの余地: 大規模図面では、ページ名が重複していないか(Visioは許容するがロジックが破綻する)の事前チェックをこの `SortArray` の直前に入れることで、事故を未然に防ぐことができる。
4. 現場のアーキテクトからの助言
- データベース連携: もしこの並び順をExcelや外部DBで管理しているなら、`Page.Name` をキーにしてIDをマッピングする辞書(`Scripting.Dictionary`)を構築せよ。ファイルシステム上の構成と図面内のページ順序を同期させることで、構成管理(CM)の自動化が可能になる。
- Undoスタックの意識: 大量に `Index` を書き換えると、VisioのUndo履歴が汚れる。必要に応じて `Application.UndoScopeID` を使用し、一連の操作を一つのトランザクションとしてラップすることを推奨する。
Visioは単なる作図ツールではない。正しく扱えば、データソースから図面を生成する「コードとしてのドキュメント」の基盤になり得る。このスクリプトを足掛かりに、君の業務を「手作業の苦役」から「自動化されたアート」へと昇華させてほしい。
