AutoCAD VBAの深淵:ファイルオープン時の「読み取り専用」ダイアログを制御するアーキテクトの矜持
AutoCADの自動化において、最も忌むべき存在は「ダイアログ」である。
バックグラウンドでバッチ処理を走らせている最中に、画面の中央に鎮座する「読み取り専用で開きますか?」という無機質な問いかけ。このGUIの介入こそが、多くの自動化システムを停止させ、開発者の胃に穴を開けてきた元凶だ。
今日は、APIの表面をなぞるような解説ではない。AutoCADの内部メモリとWindowsメッセージの流儀を理解し、この「ダイアログの呪縛」を完全に掌握するための極限の技術を授ける。
—
1. なぜ「FileDialog」は制御不能なのか
AutoCADの `Application.Documents.Open` メソッドは、ファイルを開く際に排他制御をチェックする。しかし、このチェックプロセスはAutoCADのメインスレッドをブロックし、ユーザー入力を待機するモーダルダイアログを呼び出す。
多くの初心者は、これを `SendKeys` で凌ごうとするが、それは禁じ手だ。なぜなら、`SendKeys` は非同期であり、Windowsメッセージキューの競合を引き起こし、AutoCADそのものを不安定にさせるからだ。
真のエンジニアは、「Windows APIによるメッセージフック」と「AutoCADのデータベース制御」の二段構えでこれを制する。
—
2. 核心的アプローチ:APIによるダイアログの無効化
AutoCADには標準で `FILEDIALOG` システム変数がある。これを `0` に設定することで、ファイルオープン時のダイアログを強制的に抑制できる。しかし、単純な代入では足りない。エラー処理中にクラッシュした場合、システム変数が `0` のまま固定され、ユーザーのGUI操作を破壊するからだ。
以下に、メモリ効率と堅牢性を極限まで高めた実装を示す。
実装コード:安全なファイルオープン・ルーチン
‘ 伝説的な堅牢性を備えたファイルオープン関数
Public Sub OpenDrawingSecure(ByVal filePath As String, ByVal readOnly As Boolean)
Dim doc As AcadDocument
Dim oldFileDialog As Integer
‘ メモリ最適化:不要なオブジェクト生成を避けるため、既存のAcadApplicationを参照
Dim acadApp As AcadApplication
Set acadApp = Application
‘ 1. 現在のシステム変数を退避
oldFileDialog = acadApp.GetVariable(“FILEDIALOG”)
‘ 2. GUIの介入を物理的に遮断
acadApp.SetVariable “FILEDIALOG”, 0
On Error GoTo ErrorHandler
‘ 3. ファイルオープン(読み取り専用フラグを明示的に指定)
‘ 第2引数がReadOnlyの制御フラグ
Set doc = acadApp.Documents.Open(filePath, readOnly)
‘ 処理終了後、必ずFILEDIALOGを復元する
acadApp.SetVariable “FILEDIALOG”, oldFileDialog
Exit Sub
ErrorHandler:
‘ 4. 異常終了時のリカバリー(最重要)
acadApp.SetVariable “FILEDIALOG”, oldFileDialog
MsgBox “ファイルオープン失敗: ” & Err.Description, vbCritical
End Sub
—
3. レガシー環境とメモリ解放の真実
VBAは、C++やC#のようなガベージコレクションを期待できない。`Documents.Open` を繰り返すと、COMオブジェクトの残滓がメモリリークを引き起こす。
- オブジェクトの明示的解放: `Set doc = Nothing` は必ず実行すること。
- イベントの無効化: 大規模なバッチ処理を行う場合、`VBAEvents` や `DocumentEvents` がオープン中に発火しないよう、一時的に `AcadApplication.Visible = False` (可能であれば)あるいは、イベントハンドラ内でのフラグ制御を徹底せよ。
—
4. シニアエンジニアへの提言:API連携の先へ
もしあなたが、数百の図面を横断して処理するシステムを構築しているのであれば、VBA単体での運用は推奨しない。
1. VB.NET (ObjectARX/Managed .NET) への移行:
`DocumentCollection.Open` メソッドは、VBAよりも遥かに細やかな制御が可能だ。`Database` オブジェクトを直接メモリに読み込む「ReadDwgFile」メソッドを使えば、GUIを介さず、高速かつダイアログを完全に回避して図面データを操作できる。
2. Windows API `FindWindow` / `PostMessage` の活用:
どうしても既存のVBA環境で、特定のダイアログを「はい」と応答させたい場合は、`User32.dll` を呼び出し、ウィンドウハンドルを特定して `WM_COMMAND` を送り込む必要がある。だが、これは最終手段だ。AutoCADのバージョンアップデートでウィンドウクラス名が変わるリスクを常に孕んでいるからだ。
—
結論:技術は「消す」ためにある
優秀な業務自動化とは、システムが何をやっているかユーザーに気付かせないことだ。ダイアログを出し、ユーザーにクリックをさせることは「敗北」である。
`FILEDIALOG` を制御し、オブジェクトを厳密に管理する。この小さな積み重ねが、何万時間という労働時間を削減する礎となる。
君たちが書くコードは、単なるスクリプトではない。会社の資産であり、技術的遺産だ。美しく、強く、そして静かな自動化を追求し続けろ。
健闘を祈る。
