Visioの墓場から脱出せよ:DocumentオブジェクトのSavedプロパティを「真に」制御する技術
Visioの自動化を志す多くのエンジニアが、最初の壁としてぶつかるのが「保存」という極めて単純かつ、実装を誤ればシステムを破綻させるプロセスだ。
「`If Not doc.Saved Then doc.Save`」
巷の入門書にはこう書かれているだろう。だが、これが通用するのはお遊びのスクリプトだけだ。真のエンジニアが制御すべきは、単なるフラグの監視ではない。メモリ上のオブジェクトの状態と、物理ディスクとの非同期な乖離(かいり)である。
今回は、VBAの深淵を覗く諸君に向けて、Visioの`Document`オブジェクトを安全かつ堅牢にハンドリングする極限の設計指針を授ける。
—
1. なぜ「Savedプロパティ」だけでは不十分なのか
Visioの`Document.Saved`プロパティは、あくまで「最後に保存されてから、何らかの変更が加えられたか」を示す内部フラグに過ぎない。しかし、自動化ツールやアドインを設計する際、以下のリスクを考慮せざるを得ない。
- ゾンビオブジェクトの存在: 親となる`Application`オブジェクトや`Document`オブジェクトが正常に解放されていない場合、`Saved`フラグが誤った状態を保持し続ける。
- ファイルロックの競合: ネットワークストレージ上のVSDXを開いている場合、単純な`Save`メソッドはI/Oエラーを招く。
- PDFエクスポートとの排他制御: 大規模な図面をPDFとして出力する際、保存処理が重なりVisioプロセスがハングアップする事象を経験した者は多いはずだ。
—
2. 堅牢な保存フロー:実装コードの真髄
単に保存を促すのではなく、「メモリの解放」と「例外処理」をセットにしたアプローチが必須となる。以下に、現場の保守性を極限まで高めた実装例を示す。
‘ @description: Documentの変更状態を判定し、安全に保存・終了処理を行う
‘ @author: Chief Architect
Public Sub SafeSaveDocument(targetDoc As Visio.Document)
‘ 引数のバリデーション(Null参照の即時排除)
If targetDoc Is Nothing Then Exit Sub
On Error GoTo ErrorHandler
‘ Documentが保存済みか否かを判定
If Not targetDoc.Saved Then
‘ ここでユーザーへの確認や、自動保存のロジックを配置する
‘ 自動化環境であれば、SaveAs等でバックアップを取る処理も検討すべき
Debug.Print “Save required for: ” & targetDoc.Name
‘ 非同期処理によるI/O負荷を避けるため、DoEventsを挟む設計も考慮せよ
DoEvents
targetDoc.Save
End If
Exit Sub
ErrorHandler:
‘ ログ出力およびオブジェクトの整合性を保つための例外処理
Debug.Print “Critical Error: ” & Err.Description
‘ 必要に応じてレジストリやイベントビューアへの書き出しを実装する
End Sub
—
3. シニアエンジニアが意識すべきメモリ最適化
VBAは「ガベージコレクションがない」という前提で書くべきだ。Visioは特にオブジェクトの階層が深く、参照カウントが複雑に絡み合う。
- 明示的な解放(Nothingの代入):
スコープが終了する直前に、使用した`Document`や`Page`オブジェクトには必ず`Set obj = Nothing`を明示せよ。これを怠ることは、メモリリークという時限爆弾を仕掛けるのと同じだ。
- APIによる排他制御:
もし、システム間連携で「別のプロセスが当該ファイルを掴んでいるか」を確認したい場合、Windows APIの`OpenFile`等を用いてロック状態を事前に検知する実装も視野に入れるべきだ。Visioの例外で落ちるのを待つ設計は、プロフェッショナルの仕事ではない。
—
4. アーキテクトからの最終提言
VisioのVBA開発において、コードを動かすことは「最低条件」に過ぎない。
1. Savedプロパティを盲信するな: 常に`On Error Resume Next`ではなく、エラーハンドラでI/Oを制御せよ。
2. PDF出力との連携: `Document.Export`メソッドを実行する前に、必ず`Saved`フラグをリセットする保存処理を完了させるフローを強制せよ。さもなくば、PDFの内容と保存されたVSDXの内容が不一致を起こす「データの汚染」が発生する。
3. イベント駆動の活用: `DocumentSaved`イベントを拾うことで、保存が完了した瞬間に後続のPDF生成処理をトリガーするイベントドリブンなアーキテクチャへ移行せよ。
VBAはレガシーではない。現代においても、OSの深部に最も近い場所で図面を操れる唯一無二のツールだ。諸君が書くその一行が、明日誰かの業務を救う、あるいは破壊する。その重みを忘れないでほしい。
技術の深淵へ、ようこそ。
