こんにちは!Visioの自動化の世界へようこそ。
これまで「マクロの記録」を使って、なんとなく図形を描画するコードは書けるようになったけれど、ふと気づくと……「ただの図なのに、ファイルサイズが数十メガバイトもある!」「なぜか動作が重い……」なんて壁にぶ和されていませんか?
実はVisioのファイル(.vsdx)は、内部で使っていない「ステンシル(マスターシェイプ)」や「スタイル」をこっそり抱え込む性質があります。図形をコピー&ペーストしたり、他の図面からパーツを引っ張ってきたりするたびに、見えないゴミがどんどん溜まっていくんです。
今回は、そんなVisioの深部を綺麗さっぱりお掃除し、ファイルサイズを劇的に軽量化する「クリーンアップ・ツール」の作り方を伝授します。ここをクリアすれば、あなたも脱・初心者!Visio VBAの裏側を完全に掌握する第一歩を踏み出せますよ。
—
なぜVisioのファイルは肥大化するのか?
Visioで図形を配置すると、その「大元(ひな形)」である Master(マスターシェイプ) がドキュメント(`Document`オブジェクト)の中に自動的に取り込まれます。
厄介なことに、その図形を画面上から削除しても、Masterはドキュメント内に残ったままになる仕様になっています。さらに、不要な文字スタイルや線のスタイル(`Style`オブジェクト)も同様です。
これを人間の手で一つひとつ消すのは、終わりのない苦行。だからこそ、VBAの出番です!
—
現場で即戦力になる!最強クリーンアップ・コード
それでは早速、現在開いているVisio図面から「使われていないマスターシェイプ」と「ユーザー定義以外のスタイル」を根こそぎ削除し、ついでに最適化して保存するVBAコードを公開します。
VBE(Visual Basic Editor)を開き、標準モジュールに以下のコードを貼り付けてください。
Option Explicit
‘ ==============================================================================
‘ 処理名: 肥大化したVSDXファイルを極限まで軽量化するクリーンアップツール
‘ 概要 : 未使用のマスターシェイプおよびカスタムスタイルを安全に削除し、保存します。
‘ ==============================================================================
Public Sub OptimizeCurrentVisioDocument()
Dim docTarget As Visio.Document
Set docTarget = ActiveDocument
‘ 念のため、Visioの画面描画を停止して処理を高速化
Application.ScreenUpdating = False
Dim initialSize As Long
Dim finalSize As Long
On Error GoTo ErrorHandler
Debug.Print “=== 軽量化処理を開始します: ” & docTarget.Name & ” ===”
‘ 1. 未使用マスターシェイプの削除
Call PurgeUnusedMasters(docTarget)
‘ 2. 未使用スタイルの削除
Call PurgeUnusedStyles(docTarget)
‘ 3. 文書の最適化保存(Compact)
‘ ※一度名前をつけて保存し直すことで、内部のXML構造を再構築しファイルサイズを削ぎ落とします
If docTarget.Path <> “” Then
Dim originalPath As String
originalPath = docTarget.Path & docTarget.Name
‘ 変更を保存
docTarget.Save
Debug.Print “=== 軽量化処理が完了しました ===”
Else
MsgBox “未保存のドキュメントです。一度保存してから実行してください。”, vbExclamation, “警告”
End If
CleanUp:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “予期せぬエラー”
Resume CleanUp
End Sub
‘ ——————————————————————————
‘ サブ処理: 未使用マスターのパージ(削除)
‘ ——————————————————————————
Private Sub PurgeUnusedMasters(ByVal doc As Visio.Document)
Dim i As Long
Dim mastersCount As Long
mastersCount = doc.Masters.Count
Dim deletedCount As Long
deletedCount = 0
‘ コレクションの削除は、インデックスのズレを防ぐために「後ろから前へ(逆順)」ループさせるのが鉄則!
For i = mastersCount To 1 Step -1
Dim mst As Visio.Master
Set mst = doc.Masters(i)
‘ 判定基準: ページ上にこのマスターから作られた図形(Shapes.Count)が一つもないか?
‘ ※ さらに、他のマスターの内部でも使われていないかチェックするのが完璧ですが、
‘ 今回は実用性を重視し「ドキュメント内のページで使われているか」を判定します。
If IsMasterUnusedInPages(doc, mst) Then
‘ 組み込みの特殊なマスター(ドキュメント固有の不可視マスターなど)を除外するため保護をチェック
On Error Resume Next
mst.Delete
If Err.Number = 0 Then
deletedCount = deletedCount + 1
Debug.Print ” [削除] マスター: ” & mst.Name
End If
On Error GoTo 0
End If
Next i
Debug.Print ” -> 削除された未使用マスター数: ” & deletedCount
End Sub
‘ ——————————————————————————
‘ 判定関数: 指定されたマスターが全ページで一度も使われていないか確認
‘ ——————————————————————————
Private Function IsMasterUnusedInPages(ByVal doc As Visio.Document, ByVal mst As Visio.Master) As Boolean
Dim pg As Visio.Page
Dim shp As Visio.Shape
IsMasterUnusedInPages = True ‘ 初期値は「使われていない」
For Each pg in doc.Pages
For Each shp in pg.Shapes
‘ 図形の Master プロパティを比較
If Not shp.Master Is Nothing Then
If shp.Master.ID = mst.ID Then
IsMasterUnusedInPages = False
Exit Function
End If
End If
Next shp
Next pg
End Function
‘ ——————————————————————————
‘ サブ処理: 未使用スタイルのパージ
‘ ——————————————————————————
Private Sub PurgeUnusedStyles(ByVal doc As Visio.Document)
Dim i As Long
Dim styleCount As Long
styleCount = doc.Styles.Count
Dim deletedCount As Long
deletedCount = 0
For i = styleCount To 1 Step -1
Dim stl As Visio.Style
Set stl = doc.Styles(i)
‘ Visioの標準スタイル(Normalなど)や、組み込みの必須スタイルは削除してはいけない
If Not stl.BuiltIn Then
‘ ここでは簡易的に「BuiltIn(組み込み)ではないカスタムスタイル」を対象に安全に削除トライ
On Error Resume Next
stl.Delete
If Err.Number = 0 Then
deletedCount = deletedCount + 1
Debug.Print ” [削除] スタイル: ” & stl.Name
End If
On Error GoTo 0
End If
Next i
Debug.Print ” -> 削除されたカスタムスタイル数: ” & deletedCount
End Sub
—
コードのここがポイント!プロが教える「秘伝のタレ」
上記のコードには、Visio VBAを極めたエンジニアならではの「こだわり(知見)」が詰まっています。初心者から一歩抜け出すために、重要なポイントを解説します。
1. コレクション操作は「後ろから前へ(逆順)」回せ!
`For i = mastersCount To 1 Step -1` という書き方に注目してください。
プログラミング初心者がやりがちなのが、`For i = 1 To mastersCount` と前から順番に消していく方法です。これをやると、要素を消した瞬間に後ろのインデックスがズレてしまい、エラーが起きて一部の要素がすり抜けてしまいます。
コレクションを削除・変更しながらループさせる時は「必ず後ろから前へ数える」。これがVBAの鉄則です。
2. `Application.ScreenUpdating = False` で爆速化
大量のオブジェクトを走査して削除する際、Visioの画面が一生懸命「今ここを消しましたよ」と再描画しようとすると、処理がものすごく遅くなります。
処理の最初に画面更新を止め、最後に復元することで、ストレスフリーな速度で動作させることができます。
3. エラーハンドリングの防壁 (`On Error Resume Next`)
Visioのマスターシェイプの中には、システム側が裏でガッチリ掴んでいて「絶対に消しちゃダメ!」という神聖な領域があります。
これをプログラムが無理やり消そうとすると、容赦なく実行時エラーで止まってしまいます。そのため、`On Error Resume Next` を使って「もし消せないシステム系なら無視して次に進む」という大人の対応をさせています。
—
陥りやすいエラーと注意点
- 「未保存のドキュメントです」と怒られる
- このツールは一度ファイルとして保存されている(パスが存在する)VSDXファイルを対象にしています。新しく開いたばかりの「ドキュメント1」の状態では `.Path` が空になるため、一度名前をつけて保存してから実行してください。
- リンクされたステンシルへの配慮
- 外部のステンシルファイル(.vssx)からドキュメントに「コピー」されたマスターは削除対象になりますが、もし図面がそのステンシルと常時リンクしている場合などは、組織の運用ルールに合わせて削除範囲を調整してください。
—
まとめ:自動化のロマンをその手に
いかがでしょうか?
普段何気なく使っているVisioも、内部の構造(`Masters` や `Styles`)を理解し、VBAでコントロールできるようになると、まるで自分の手足のように操れるようになります。
「ファイルが重くてメールに添付できない!」そんな社内の悲鳴を、このクリーンアップ・ツールを一発走らせるだけでスマートに解決してあげてください。「お、できる奴だな」と一目置かれること間違いなしです。
それでは、快適なVisio自動化ライフを!次のステージでお会いしましょう。
