Visio VBAを掌握する極限の知見:機密情報・メタデータの自動消去と図面ガバナンスの極意
図面の外部納品、あるいは社内共有において、図面そのものの美しさや正確性と同じくらい――いや、それ以上に厳格に担保されなければならないものがある。それが「メタデータの浄化」だ。
プロパティに刻まれた作成者名、組織名、編集履歴、そして隠しレイヤーや過去の改訂版の残滓。これらはビジネスの現場において、しばしば致命的な情報漏洩のトリガーとなる。
VisioのGUIから「ファイル > 情報 > ドキュメントの検査」をポチポチと手動で操作しているようでは、システムアーキテクトを名乗る資格はない。数千枚に及ぶ図面群を扱うエンタープライズ環境において、このプロセスは完全に自動化され、かつ一瞬で完了しなければならない。
今回は、Visio VBAの根幹をなす `Document.RemoveHiddenInformation` メソッドを極限まで使い倒し、堅牢な図面クリーニングパイプラインを構築する手法を解説する。
—
1. Visioオブジェクトモデルの暗部:隠しデータの正体
Visioの `.vsdx`(あるいは旧 `.vsd`)ファイルは、単なるベクター画像のコンテナではない。実態はXMLのパッケージ(Open Packaging Conventions)であり、以下のような機密データが容易に残留する。
- DocumentProperties(Core/Extended): 作成者、管理者、会社名、リビジョン番号、編集時間。
- 非表示レイヤー・オフスクリーンシェイプ: 削除したつもりの古い設計データや、カンバス外に退避させた機密ノート。
- カスタムプロパティ(Shape Data)のメタデータ: 内部的なコスト算出ロジックや、開発者のコメント。
これらを一網打尽にするのが、Visio 2010以降(実質的には近年のバージョンで強化された)に実装されている `Document.RemoveHiddenInformation` メソッドである。しかし、このメソッドは強力であるがゆえに、どのフラグを立てて実行するかを誤ると、必要なデータまで吹き飛ばす諸刃の剣でもある。
—
2. 実装コード:エンタープライズ品質のクリーンアップエンジン
以下に提供するコードは、単にメソッドを呼び出すだけの稚拙なものではない。エラーハンドリング、オブジェクトの明示的解放によるメモリリークの防止、そして処理結果の監査ログ出力までを網羅した、実戦投入仕様のプロシージャだ。
Option Explicit
‘ ==============================================================================
‘ módulo: ModDataSanitizer
‘ 概要 : アクティブドキュメントの機密情報・メタデータを完全消去する
‘ 著者 : 伝説のチーフアーキテクト
‘ ==============================================================================
Public Sub ExecuteSanitizationPipeline()
Dim vsoDoc As Visio.Document
Dim startTime As Double
startTime = Timer
‘ 1. アプリケーションの最適化(描画停止による爆速化とメモリ保護)
With Visio.Application
.ScreenUpdating = False
.Interactive = False
.ShowProgressWindow = False
End With
On Error GoTo ErrorHandler
‘ 2. ターゲットドキュメントの取得
If Visio.Application.Documents.Count = 0 Then
MsgBox “処理対象のドキュメントが開かれていません。”, vbCritical, “ガバナンスエラー”
GoTo Finally
End If
Set vsoDoc = Visio.Application.ActiveDocument
‘ 3. 読取専用チェック(書き込み権限がない場合の早期リターン)
If vsoDoc.ReadOnly Then
MsgBox “指定されたドキュメントは読取専用です。クリーンアップを中断します。”, vbExclamation, “警告”
GoTo Finally
End If
‘ 4. RemoveHiddenInformation の実行
‘ VISVIS_RHI_ フラグをビット単位でOR結合し、対象を精密に指定する。
‘ ※ここでは全主要メタデータ(プロパティ、非表示オブジェクト、コメント等)を指定
Dim rhiFlags As Long
rhiFlags = Visio.VisRemoveHiddenInfoFlags.visRHIAll ‘ 全削除フラグ(環境により定数名・数値を調整)
‘ 【重要】VisioのバージョンやAPI仕様に応じた安全策として、
‘ 個別フラグの合算が必要な場合はここに記述する。
‘ 例: rhiFlags = visRHIProperties Or visRHIHiddenLayers Or visRHICoauthingData
vsoDoc.RemoveHiddenInformation (rhiFlags)
‘ 5. 変更の確定と強制保存(必要に応じ別名保存を推奨)
‘ 今回は上書き保存とするが、本番環境では必ずバックアップを別系統で取得すること。
vsoDoc.Save
Debug.Print “[Sanitizer] 正常終了: ” & vsoDoc.Name & ” (処理時間: ” & Format(Timer – startTime, “0.00秒”) & “)”
MsgBox “機密情報およびメタデータの消去が完了しました。”, vbInformation, “クリーンアップ成功”
Finally:
‘ 6. 厳格なオブジェクト解放(COMの参照カウンタを確実にデクリメント)
Set vsoDoc = Nothing
‘ 7. アプリケーション状態の復元
With Visio.Application
.ScreenUpdating = True
.Interactive = True
.ShowProgressWindow = True
End With
Exit Sub
ErrorHandler:
‘ 異常系ハンドリング
Dim errNum As Long: errNum = Err.Number
Dim errDesc As String: errDesc = Err.Description
‘ ログ出力(必要に応じてテキストファイルやEventViewerへ)
Debug.Print “[Sanitizer Error] 致命的エラー (#” & errNum & “): ” & errDesc
MsgBox “クリーンアップ中に予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & errNum & vbCrLf & _
“詳細: ” & errDesc, vbCritical, “システムエラー”
Resume Finally
End Sub
—
3. チーフアーキテクトが教える「メモリとパフォーマンス」の極意
上記のコードを見て、「単なる `Save` メソッドじゃないか」と思ったならば、VBAの本質を見誤っている。大規模なVisioインフラストラクチャにおいて、以下の3点がシステム安定性の生死を分ける。
① 描画スレッドの完全凍結 (`ScreenUpdating = False`)
Visioは、シェイプの削除やメタデータの書き換えが発生するたびに、GUIの再描画(レンダリング)走査を走らせようとする。これが数万個のオブジェクトを持つP&ID(配管計装図)や建築図面であれば、数分間のフリーズ、最悪の場合はOut of Memoryを引き起こす。
`ScreenUpdating = False` と `Interactive = False` をセットで宣言し、OSのメッセージキューからVisioのGUIを描画ループから完全に切り離すこと。これがプロの処理速度だ。
② 明示的なオブジェクトのNULLクリアとCOM参照管理
VBAのガベージコレクションは頼りにならない。特に複数のドキュメントをループ処理で一括クリーンアップするバッチツールを書く場合、`Set vsoDoc = Nothing` を怠ると、COMコンポーネントへの参照がメモリ上に残留し、ヒープ断片化(Memory Fragmentation)を引き起こす。
バッチ処理のイテレーション内では、必ずオブジェクト変数を解放し、VBAの内部ヒープをクリーンに保て。
③ バックアップ戦略の不可避性
`RemoveHiddenInformation` は、一度実行して上書き保存してしまうと、消去されたメタデータや非表示レイヤーを復元することは不可能である。
システム間連携(例:C#やPythonの外部オーケストレーターからの呼び出し)においてこのVBAをキックする場合は、必ず別ディレクトリへ元ファイルをバックアップした上で、一時ファイルに対してクリーンアップを実行するアーキテクチャ設計が求められる。
—
4. システム間連携への拡張:VBAの枠を超えて
社内ポータルや文書管理システム(DMS)からこの処理を自動化したい場合、VBA単体で完結させる必要はない。
WSH(Windows Script Host)や外部のVB.NET / PythonプロセスからVisioをCOMオートメーション(`Visio.Application`)経由で起動し、上記のプロシージャをサイレント実行することが可能だ。
// C# (COM Interop) による外部からの安全なクリーンアップ呼び出しの概念
var visioApp = new Visio.Application();
visioApp.Visible = false;
visioApp.ScreenUpdating = false;
Visio.Document doc = visioApp.Documents.Open(@”C:\secured\blueprint.vsdx”);
// ※注意: C#側から直接RemoveHiddenInformationのフラグを叩く場合も、COMの型安全性を意識する
doc.RemoveHiddenInformation((int)Visio.VisRemoveHiddenInfoFlags.visRHIAll);
doc.Save();
doc.Close();
visioApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(visioApp);
VBAはこの外部ラッパーからの「最も軽量で確実な実行エンジン」として機能する。レガシーなマクロ資産を捨て去るのではなく、APIの極限までチューニングしてモダンなシステムの一部として組み込むことこそが、真のレガシー保守の美学である。
—
総括
図面のメタデータ漏洩は、技術的なミスではなく「プロセスの怠慢」だ。
今回解説した `Document.RemoveHiddenInformation` のVBA実装をあなたの組織の標準パイプラインに組み込むことで、人的ミスを排除し、完全無欠なセキュリティガバナンスを実現してほしい。
コードは嘘をつかない。アーキテクチャの美しさは、細部のメモリ管理とエラーハンドリングの執念に宿る。
