【実務・中級編】保存確認ダイアログを出さずに閉じる:Document.Savedプロパティとサイレントクローズ – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを掌握する極限の知見:保存確認ダイアログを出さずに閉じる技術

開発プロジェクトの現場で、Visioの図面を大量にバッチ処理するマクロを書いたとき、最もフラストレーションが溜まる瞬間はどこか。

そう、「処理が終わったはずなのに、画面のどこかでモーダルダイアログが鎮座し、バックグラウンド処理が完全にフリーズしている」という事態だ。

特に `ActiveDocument.Close` や `Document.Close` をループ内で呼び出した際、「変更を保存しますか?」というあの忌々しい確認ダイアログがポップアップする。自動化スクリプトにとって、ユーザーインタラクションを要求するダイアログは悪(バグ)でしかない。

今回は、Visioのオブジェクトモデルが持つ「ドキュメントのライフサイクルと保存フラグの真実」を解き明かし、完全無人・サイレントで大量のファイルを安全に閉じ、処理し切るための極限のテクニックを伝授する。

1. なぜ「何もしていない」のに保存確認が出るのか?

Visio VBAにおける `Document` オブジェクトには、`Saved` プロパティという極めて重要な状態フラグが存在する。

多くの開発者は、「ファイルを新しく開いて、何も変更せずに閉じるんだから、ダイアログなど出ないはずだ」と思い込む。しかし、Visioのランタイムは冷酷だ。
プログラムからファイルを開いた瞬間にビューポートが初期化されたり、ページ内のシェイプが自動整列のトリガーを引いたり、あるいは単に `ActiveWindow.Page` が切り替わったという内部イベントだけで、Visioは「このドキュメントは変更された(Dirty状态になった)」とみなすことがある。

結果として、開発者の意図とは裏腹に `Saved = False` となり、閉じる際にダイアログが爆誕する。

非効率なアプローチ(やってはいけないアンチパターン)

‘ 【悪手】ダイアログを無視するためにSendKeysを使う(絶対にNG)
SendKeys “%N”, True ‘ 「いいえ(N)」をキーボードシミュレーションで送る
doc.Close

このような場当たり的なハックは、フォーカスが外れた瞬間に別のウィンドウにキーが飛び、デスクトップ全体を破壊する時限爆弾となる。我々はエンジニアである。オブジェクトモデルを正しく制御して制圧すべきだ。

2. 堅牢なサイレントクローズの設計原則

Visioでファイルを安全かつ完全にサイレントに閉じるための鉄則は、以下の2点に集約される。

1. `Document.Saved` プロパティの明示的な制御

  • 変更を破棄して閉じたい場合は、明示的に `doc.Saved = True` に偽装(あるいは状態を確定)させてから閉じる。
  • 変更を保存して閉じたい場合は、`doc.Save` または `doc.SaveAs` を事前に実行する。

2. エラーハンドリングによるリソースリークの防止

  • ループ処理中に予期せぬエラーが発生した場合でも、オープンしたドキュメントハンドルが宙ぶらりんにならないよう、確実にクローズ処理を通す構造にする。

3. プロダクションコード:一括処理エンジン実装例

実務でそのまま使える、堅牢性を極限まで高めたバッチ処理のモジュールを提示する。
指定フォルダ内のすべての `.vsd` / `.vsdx` ファイルを読み込み、何らかの処理を行った後、一切のダイアログを出さずにサイレントクローズして次のファイルへ進むテンプレートだ。

Option Explicit

”’

”’ 指定フォルダ内のVisioファイルを一括処理し、ダイアログを出さずに閉じるメインプロシージャ
”’

Public Sub BatchProcessVisioFiles()
Dim targetDir As String
targetDir = “C:\VisioWorkSpace\TargetFiles\” ‘ 処理対象のフォルダパス

If Dir(targetDir, vbDirectory) = “” Then
MsgBox “指定されたフォルダが存在しません: ” & targetDir, vbCritical
Exit Sub
End If

Dim fileName As String
fileName = Dir(targetDir & “.vsd”)

‘ 画面描画と警告を完全に停止し、処理速度を最大化する
Application.ScreenUpdating = False
Application.ShowChanges = False

On Error GoTo ErrorHandler

Dim targetPath As String
Dim targetDoc As Visio.Document

Do While fileName <> “”
targetPath = targetDir & fileName

‘ 読取専用、または通常の非表示オープン(バックグラウンド処理の場合)
‘ ※Visioの仕様上、完全にHeadless(UIなし)で開くことはできないため、
‘ ウィンドウを最小化するか、画面描画OFFで高速化する。
Set targetDoc = Application.Documents.Open(targetPath)

‘ ==========================================
‘ ここに実業務の処理ロジックを記述
‘ 例: 全ページのシェイプ情報を書き換える等
‘ ==========================================
Call ProcessDocument(targetDoc)

‘ 【極限の知見】
‘ 変更を保存して閉じる場合:
‘ targetDoc.Save
‘ targetDoc.Close

‘ 変更を破棄して(または変更ナシとして)完全にサイレントに閉じる場合:
‘ Visioに「このドキュメントは保存済みである」と強制的に認識させることで、
‘ Closeメソッド実行時の「保存確認ダイアログ」の割り込みを封殺する。
targetDoc.Saved = True
targetDoc.Close

‘ 次のファイルへ
fileName = Dir()
Loop

CleanUp:
‘ 画面描画と警告を復元
Application.ScreenUpdating = True
Application.ShowChanges = True
MsgBox “すべてのファイルのバッチ処理が完了しました。”, vbInformation
Exit Sub

ErrorHandler:
‘ 異常終了時もVisioの環境設定が破壊されないように必ず復元ルートを通す
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical

‘ 開いたままのドキュメントがあれば強制終了(保存せずに閉じる)
If Not targetDoc Is Nothing Then
On Error Resume Next
targetDoc.Saved = True
targetDoc.Close
On Error GoTo 0
End If

Resume CleanUp
End Sub

”’

”’ ドキュメント個別に対するビジネスロジック
”’

Private Sub ProcessDocument(ByRef doc As Visio.Document)
‘ サンプルとして、プロパティの書き換えやレイヤー操作などをここに記述
Dim pg As Visio.Page
For Each pg in doc.Pages
‘ 例:何らかの処理
Next pg
End Sub

4. チーフアーキテクトからの実務アドバイス:データベース連携時の罠

もしこのバッチ処理の中で、処理結果を外部データベース(SQL ServerやAccessなど)にログとして書き込んだり、ファイルサーバー上の共有パスへ排他制御付きで上書き保存する設計にする場合、以下の「重み」を忘れてはならない。

1. COMオブジェクトの参照解放(Release)の徹底
`For Each` ループ内で `Visio.Shape` や `Visio.Page` を取得する際、VBAの内部ではCOMの参照カウンタがインクリメントされている。大量のファイルをループ処理するアーキテクチャでは、これらがメモリリークを引き起こし、中盤からVisioの動作が劇的に重くなるか、メモリ不足でクラッシュする。
オブジェクト変数(`pg`, `shp` など)は、使い終わったら明示的に `Set xxx = Nothing` で解放する習慣をつけよ。
2. ファイルの排他ロックエラーのハンドリング
ネットワークドライブ上のファイルを一括処理する場合、他のユーザーが開いているファイルに遭遇すると `Documents.Open` が実行時エラー(エラー番号:-2034 等)を吐く。
`On Error Resume Next` を局所的に挟むか、ファイル属性をチェックするガード節を設け、エラーファイルを華麗にスキップしてログ(CSVやDB)に「スキップ:使用中」と書き残す仕組みこそが、真にプロフェッショナルな業務自動化システムの姿である。

退屈なコードのコピペから脱却し、オブジェクトのライフサイクルを完全に掌握した者だけが、真に安定した堅牢な自動化システムを構築できる。現場の信頼を勝ち取るエンジニアであれ。

タイトルとURLをコピーしました