Visioの「肥満化」を外科手術する:未使用マスターシェイプの完全除去とメモリ最適化の極意
Visioの`.vsdx`ファイルを長く運用していると、誰もが直面する壁がある。ファイルサイズの肥大化だ。数MBで済むはずの図面が、気づけば数十MBに膨れ上がる。その主犯は、ドキュメントステンシルに溜め込まれた「ゾンビのようなマスターシェイプ」である。
今回は、単に「削除する」というレベルを超え、Visioのオブジェクトモデルの深層に触れ、システムリソースを極限まで効率化するアーキテクトの視点で、この問題を解決する。
1. なぜ「未使用マスター」がファイルサイズを殺すのか
Visioは、一度図面にドラッグ&ドロップされたシェイプの定義を、たとえ画面上から削除してもドキュメントステンシル内に保持し続ける仕様になっている。これはUndo履歴の管理や再配置の利便性のためだが、大規模な図面編集を繰り返すと、ゴミの山と化す。
VBAでこれを処理する場合、単に `Master.Delete` を呼び出すだけでは不十分だ。オブジェクトの参照カウント、メモリリーク、そしてファイル保存時のストリーム書き込み負荷を考慮した「クリーンアップ・パイプライン」を構築する必要がある。
2. 破壊的クリーンアップの実装コード
以下のコードは、ドキュメント内の全ページ・全シェイプを走査し、どこからも参照されていないマスターを特定して破棄する「外科手術」の手法である。
Option Explicit
‘ 伝説のアーキテクトによる、高速かつ安全なマスターシェイプ削除ロジック
Public Sub PurgeUnusedMasters()
Dim doc As Visio.Document
Dim mst As Visio.Master
Dim i As Long
Set doc = ActiveDocument
‘ 処理中の画面更新を停止し、パフォーマンスを最大化(必須の作法)
Application.ScreenUpdating = False
‘ ドキュメントステンシルを逆順で走査(削除によるインデックスズレを防ぐ基本)
For i = doc.Masters.Count To 1 Step -1
Set mst = doc.Masters(i)
‘ Master.CanDelete を確認し、システム予約シェイプを保護
If mst.CanDelete Then
‘ 参照カウントを確認し、ゼロであれば削除
‘ 厳密にはシェイプの依存関係をチェックするが、
‘ シンプルかつ強固な軽量化にはこのアプローチが最短
If Not IsMasterInUse(doc, mst) Then
Debug.Print “Purging unused master: ” & mst.Name
mst.Delete
End If
End If
Next i
‘ オブジェクトの解放
Set mst = Nothing
Set doc = Nothing
Application.ScreenUpdating = True
End Sub
‘ 依存関係の判定ロジック
Private Function IsMasterInUse(doc As Visio.Document, mst As Visio.Master) As Boolean
Dim pg As Visio.Page
Dim shp As Visio.Shape
‘ 全ページの全シェイプを舐めて、このマスターを元に作られたものがあるか判定
For Each pg In doc.Pages
For Each shp In pg.Shapes
If Not shp.Master Is Nothing Then
If shp.Master.Name = mst.Name Then
IsMasterInUse = True
Exit Function
End If
End If
Next
Next
IsMasterInUse = False
End Function
3. シニアエンジニアが押さえるべき「極限の知見」
1. 参照カウントとガベージコレクションの罠
VBAはCOMベースの言語だ。`Set mst = Nothing` を怠ることは、メモリリークの種を撒くことに等しい。特に、数千のマスターを操作するループ内でオブジェクト変数を再利用せず生成し続けると、Visioのプロセスが不安定になる。必ずループの終了時には明示的な解放を行え。
2. ファイルI/Oのボトルネック回避
`ActiveDocument.Save` を実行する際、Visioは内部でXMLストリームを再構築する。未使用マスターが残っていると、不要なバイナリデータまで書き出されるため、I/O負荷が跳ね上がる。
さらに大規模な環境では、Windows APIの `FlushFileBuffers` を呼び出し、OSレベルでの書き込み完了を待機させる実装も検討すべきだが、基本的には「保存前のクリーンアップ」が最も効率的な最適化である。
3. PDF出力との連携
PDF出力時は、これらの「不要なメタデータ」がレンダリングエンジンにも悪影響を及ぼす。PDF生成の直前に `PurgeUnusedMasters` を呼び出す自動化ルーチンを組むだけで、PDFのファイルサイズは劇的に改善されるはずだ。
最後に:自動化の真髄
「動くコード」を書くことは、中級者の到達点だ。
しかし、「リソースの寿命を見極め、システムに負荷をかけずに図面という生命体をメンテナンスする」のが、真のエンジニアの仕事である。
このコードをあなたのオートメーション・ライブラリに組み込み、肥大化したレガシーファイルを過去のものに変えてほしい。それが、Visioを掌握するということだ。
