Visio VBAの深淵:Document.NameとFullNameの境界線で「未保存の亡霊」を制する
Visioのオートメーションにおいて、最も初歩的かつ致命的な罠は「ドキュメントのライフサイクル管理」にある。多くの開発者が `ActiveDocument.Save` を呼び出し、実行時エラー(エラー番号:-2032646270など)でシステムを停止させる。
「まだ一度も保存されていないドキュメント」に対して、OSのファイルシステムパスを要求すれば破綻するのは自明の理だ。本稿では、Documentオブジェクトの構造を解体し、堅牢な自動退避ロジックを実装するためのアーキテクト視点の解法を提示する。
—
1. オブジェクトモデルの真実:Name vs FullName
Visio VBAにおける `Document` オブジェクトのプロパティには、明確な役割の分断がある。
- `Document.Name`: メモリ上の識別子。保存の有無に関わらず、Visioが内部的に割り当てた仮称(例: “Drawing1″)を返す。これは「ファイルパス」ではない。
- `Document.FullName`: ファイルシステム上の物理パス。ドキュメントがディスクに書き出された瞬間にのみ、有効な文字列(”C:\Path\To\File.vsdx”)を持つ。
未保存ドキュメントの判定ロジックにおいて、`FullName` の先頭を評価するのはアマチュアのやり方だ。真のプロフェッショナルは、「Pathプロパティが空文字列であるか否か」で判断する。
—
2. 実装:安全な自動退避エンジン
以下は、未保存ドキュメントを検出し、指定ディレクトリへタイムスタンプ付きで強制保存する堅牢なモジュールである。
Option Explicit
‘ メモリリークを防ぐため、オブジェクト参照は最小限に留める
Public Sub RobustAutoSave(ByVal targetDoc As Visio.Document)
Dim savePath As String
Dim fileName As String
Dim timestamp As String
‘ 1. オブジェクトの妥当性検証
If targetDoc Is Nothing Then Exit Sub
‘ 2. Pathプロパティで「保存済み」か否かを判定
‘ Pathが空なら、それは未保存の新規ドキュメントである
If Len(targetDoc.Path) = 0 Then
timestamp = Format(Now, “yyyyMMdd_HHmmss”)
fileName = “Backup_” & timestamp & “.vsdx”
savePath = Environ(“USERPROFILE”) & “\Desktop\” & fileName
On Error GoTo ErrorHandler
‘ 保存処理(SaveAsを使用し、現在のDocumentオブジェクトを書き換える)
targetDoc.SaveAsEx savePath, visSaveAsWS
Debug.Print “未保存ドキュメントを安全に退避しました: ” & savePath
Else
‘ 保存済みドキュメントは上書き保存
targetDoc.Save
End If
Exit Sub
ErrorHandler:
‘ ログ出力やエラーハンドリング(必要に応じてWindowsイベントログへ出力)
Debug.Print “保存失敗: ” & Err.Description
End Sub
—
3. シニアエンジニアのための最適化知見
オブジェクトの解放とメモリ管理
VBAはガベージコレクションを搭載しているが、VisioのようなCOMサーバーを跨ぐ処理では、明示的な `Set obj = Nothing` が重要だ。特に大規模なドキュメントをループ処理する際は、参照カウントを意識しなければ、Visioプロセスがメモリ上に残留し「ゾンビプロセス」化する。
Windows APIによるファイルシステム操作
単純な `SaveAs` ではなく、保存先のディレクトリが存在しない場合を考慮し、APIを併用してディレクトリ階層を動的に生成する設計を推奨する。`MakeSureDirectoryPathExists` (Dbghelp.dll)を呼び出すことで、堅牢性は格段に向上する。
レガシー保守の極意
古のVisioアドインやマクロを保守する際、最も注意すべきは「マクロ記録されたコード」をそのまま製品版に組み込むことだ。記録されるコードは `Application` や `ActiveWindow` に依存しすぎる。
常に `TargetDocument` を引数として受け取る疎結合な関数 を設計せよ。これにより、テストコードからの呼び出しが容易になり、将来的なリファクタリングが劇的に楽になる。
—
結びに代えて:自動化の先にあるもの
Visio VBAは「レガシー」と揶揄されることもあるが、そのオブジェクトモデルの緻密さは現代のWeb APIよりも遥かに強力だ。ドキュメントのライフサイクルを完全に掌握することは、業務自動化の土台である。
未保存のドキュメントを「エラーの種」とするか、あるいは「安全に回収される資産」とするか。その差は、あなたがオブジェクトの内部構造をどれだけ深く理解しているか、その一点に集約される。
コードは嘘をつかない。境界条件を疑い、メモリを慈しみ、システムの静寂を守れ。それが、我々エンジニアの責務である。
