【AutoCAD VBAの真髄】「保存しますか?」の呪縛を解く――Savedプロパティを制御する極限の最適化
AutoCADのオートメーションにおいて、最も「素人臭い」挙動の一つが、読み取り専用で開いたはずの図面を閉じる際に表示される「変更を保存しますか?」という無意味なダイアログだ。
このダイアログは、単なるユーザーインターフェースの問題ではない。バッチ処理や大規模な図面管理システムにおいて、このダイアログは「システムを停止させる地雷」と同義である。今回は、`AcadDocument.Saved`プロパティを軸に、メモリ管理からAPIレベルの制御まで、現場のプロが知るべき「制御の極意」を説く。
—
1. Savedプロパティの本質と「偽りのクリーン状態」
AutoCADのオブジェクトモデルにおいて、`Saved`プロパティはドキュメントの変更状態を示すブール値だ。しかし、このプロパティは単なるフラグではない。AutoCADのデータベースエンジンが、カレントドキュメントのメモリ内データとディスク上のファイルを整合性として認識しているかを示す「同期フラグ」である。
我々がコードで `doc.Saved = True` と記述する行為は、AutoCADに対して「お前の抱えているメモリ上のデータは、ディスク上のデータと完全に同期していると見なせ」と強制的に宣言させることを意味する。
2. 実践的コード:無駄なダイアログを封殺する
単に `Saved = True` とするだけでは不十分なケースが多い。特に、コマンド操作が介在する場合や、外部参照(XRef)の再ロードが発生した場合は、イベントリスナーがフラグを上書きする。以下のコードは、実戦レベルで利用可能な「強制クリーン化」の定石だ。
‘ ——————————————————————
‘ @brief: 図面を一切の確認ダイアログを出さずに閉じるための最適化ルーチン
‘ @note: Savedフラグの強制書き換えとオブジェクト解放の作法
‘ ——————————————————————
Public Sub ForceCloseDocument(ByVal targetDoc As AcadDocument)
On Error GoTo ErrorHandler
‘ 1. 未保存フラグを強制的にクリーン状態に書き換える
‘ これにより、AutoCAD内部のデータベース状態管理を欺く
If Not targetDoc.Saved Then
targetDoc.Saved = True
End If
‘ 2. Closeメソッドにて明示的に終了
‘ acSaveChangesではなく、変更を破棄する引数を選択する
targetDoc.Close SaveChanges:=False
‘ 3. オブジェクト参照の即時解放
‘ VBAのガベージコレクションを待たず、明示的にNothingを代入し
‘ メモリリークを防止する(特にループ処理内では必須)
Set targetDoc = Nothing
Exit Sub
ErrorHandler:
Debug.Print “Error: ” & Err.Description
‘ システムのクラッシュを防ぐため、エラーを握りつぶさずログに出力せよ
End Sub
3. シニアエンジニアが意識すべき「隠れたトリガー」
`Saved = True` を設定しても、なおダイアログが出る場合は、以下の3点を疑え。
- システム変数 `FILEDIA` の罠:
システム変数 `FILEDIA` が `0` になっていると、一部のコマンド処理が標準入力へ強制的にリダイレクトされ、保存ダイアログの挙動が予測不能になる。
- 不可視の「汚染」:
`AcDbObject` の一部は、読み込み操作だけでメモリ上のタイムスタンプが更新される。特にカスタムオブジェクトやサードパーティのARXが常駐している場合、`Saved = True` の直後にイベントが発生し、フラグが `False` に戻ることがある。
- Windows APIによる制御:
どうしてもダイアログを強制終了させたい場合、`FindWindow` APIを使用して、AutoCADのダイアログハンドルを検出し、`WM_CLOSE` メッセージを送るという最終手段もあるが、これは「対症療法」だ。アーキテクチャの根本を疑うべきである。
4. 極限の最適化:メモリ管理とライフサイクル
VBAはCOMベースの言語であり、オブジェクトの生存期間(ライフサイクル)を管理するのはエンジニアの責務だ。特に、`AcadApplication` や `AcadDocument` への参照をモジュールレベルで保持し続けると、AutoCADを終了させてもプロセスが残存する「ゾンビプロセス」を引き起こす。
- 参照を局所化せよ: `AcadDocument` は可能な限り関数内で宣言し、終了直後に `Nothing` を代入せよ。
- イベントの無効化: 大量の図面を連続処理する場合、`AcadDocument.Activate` 等のイベントハンドラが余計なフラグ変更を引き起こす。処理中は `Application.EnableEvents = False` を活用し、イベントを一時停止させるのが「プロの所作」だ。
—
アーキテクトからの提言
AutoCAD VBAはレガシーと言われることもある。しかし、その内部で動いているのは、何十年もの歴史を積み上げた堅牢なデータベースエンジンだ。`Saved` プロパティを制御するということは、単にダイアログを消すことではない。AutoCADのエンジンに対し、開発者が処理の完全なコントロール権を行使するということだ。
コードは、常に「次に誰がメンテナンスしてもおかしくない」状態を維持しつつ、マシンレベルでは最大限のパフォーマンスを絞り出す。それが、真の業務自動化エンジニアの矜持である。
諸君、まずはこのコードを実装し、無駄なクリック作業から解放された時間を、より創造的な設計業務に充ててほしい。
