【実務・中級編】【初心者向け】AcadApplication.Visible = False 時の「ダイアログ停止」対策:エキスパート変数を駆使した完全バックグラウンド処理 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見

【初心者向け】AcadApplication.Visible = False 時の「ダイアログ停止」対策:エキスパート変数を駆使した完全バックグラウンド処理

開発プロジェクトのリーダーである私のもとに、よくこんな相談が持ち込まれる。
「夜間バッチで大量の図面を一括処理するVBAマクロを作ったのですが、途中で『上書きしますか?』や『フォントが見つかりません』といったダイアログが出て止まってしまうんです。画面(`Visible = False`)にしているのに、なぜクリック待ちでフリーズするのでしょうか?」

――答えはシンプルだ。AutoCADの「心臓部(コアエンジン)」は、画面が見えなかろうがユーザーからの入力を真面目に待ち続けているからだ。

今回は、AutoCAD VBAによる完全バックグラウンド処理の要諦と、実務で絶対に避けて通れない「ダイアログ・デスロック」を回避するプロの定石を授けよう。

—

なぜ `Visible = False` だけでは不十分なのか?

初心者が陥る最大の罠が、「CAD画面を非表示にすれば、あらゆるポップアップは消えるはずだ」という誤解だ。

`AcadApplication.Visible = False` は、あくまで「UI(ユーザーインターフェース)の描画とウィンドウを隠している」に過ぎない。AutoCADのCOMサーバーの背後では、レイアウトの修復、未定義フォントの置換確認、同名ファイルの存在確認など、通常であれば人間がダイアログボックスで「OK」を押すべきイベントが容赦なく発生している。

UIがないバックグラウンド状態でこれらが起きると、VBAの実行スレッドは永遠に応答のないダイアログの「OKボタン」を待ち続ける(=フリーズする)ことになる。これが、完全自動化の夢を打ち砕く「ダイアログ・デスロック」の正体だ。

—

解決の鍵:システム変数の「事前掌握」

この問題を根本から断つには、AutoCADのシステム変数をVBAから操り、「余計な確認を一切させない(デフォルトで常にYes/続行を選ぶ)状態」を強制的に作り出す必要がある。

ここで登場するのが、以下の3つのシステム変数だ。

1. `FILEDIA` (ファイルダイアログ表示)

  • `0` に設定すると、ファイル保存やオープン時のダイアログを抑制し、コマンドラインからの文字列入力を強制する。

2. `CMDECHO` (コマンドエコー)

  • `0` に設定すると、コマンドラインへの出力ログを抑制し、処理速度を向上させるとともに余計な割り込みを防ぐ。

3. `EXPERT` (エキスパートモード)

  • 通常なら「本当に上書きしますか?」と聞いてくる危険な操作に対して、警告をスキップして強制実行させる(レベルを `5` などに引き上げる)。

—

【プロダクションコード】堅牢なバックグラウンド処理の模範実装

実務でそのまま使える、エラーハンドリングとシステム変数の退避・復元を完璧に網羅したコードテンプレートを提示する。

プロの鉄則として、「マクロが異常終了しても、システム変数が変更されたままユーザーの通常作業環境を破壊しないこと」が挙げられる。必ず `On Error` によるクリーンアップ処理を組み込むべし。

Option Explicit

”’

”’ 複数図面のバッチ処理を完全バックグラウンドで安全に実行するメインプロシージャ
”’

Sub ExecuteBackgroundBatchProcess()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument

‘ — 1. システム変数の退避用変数 —
Dim oldFileDia As Integer
Dim oldCmdEcho As Integer
Dim oldExpert As Integer

‘ 処理対象のファイルパス(例)
Dim targetFiles(1 To 2) As String
targetFiles(1) = “C:\Works\DrawingA.dwg”
targetFiles(2) = “C:\Works\DrawingB.dwg”

On Error GoTo ErrorHandler

‘ — 2. AutoCADインスタンスの取得または起動 —
‘ 既存のインスタンスにアタッチするか、新規にバックグラウンド起動する
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application”)
If acadApp Is Nothing Then
Set acadApp = New AutoCAD.Application
End If
On Error GoTo ErrorHandler

‘ — 3. 【最重要】バックグラウンド化とダイアログ抑制の設定 —
‘ 現在のシステム変数を退避
oldFileDia = acadApp.GetSystemVariable(“FILEDIA”)
oldCmdEcho = acadApp.GetSystemVariable(“CMDECHO”)
oldExpert = acadApp.GetSystemVariable(“EXPERT”)

‘ ダイアログおよび確認プロンプトを完全抑制
acadApp.SetSystemVariable “FILEDIA”, 0
acadApp.SetSystemVariable “CMDECHO”, 0
acadApp.SetSystemVariable “EXPERT”, 5 // 警告を無視して強制実行

‘ 画面を非表示にする(※デバッグ時は True にすると挙動が追えて便利)
acadApp.Visible = False

‘ — 4. バッチ処理ループ —
Dim i As Long
For i = LBound(targetFiles) To UBound(targetFiles)
If Dir(targetFiles(i)) <> “” Then
‘ 図面を開く(FILEDIA=0のおかげでプロンプトが出ない)
Set acadDoc = acadApp.Documents.Open(targetFiles(i))

‘ —————————————-
‘ ここに実際の図面加工ロジックを記述
‘ 例:特定レイヤの削除、文字の置換など
Call ProcessDrawing(acadDoc)
‘ —————————————-

‘ 上書き保存(警告なしで強制上書き)
acadDoc.Save

‘ 図面を閉じる
acadDoc.Close False
Set acadDoc = Nothing
End If
Next i

‘ — 5. 正常終了時のクリーンアップ —
‘ 画面を再表示してシステム変数を元の値に戻す
acadApp.Visible = True
acadApp.SetSystemVariable “FILEDIA”, oldFileDia
acadApp.SetSystemVariable “CMDECHO”, oldCmdEcho
acadApp.SetSystemVariable “EXPERT”, oldExpert

MsgBox “すべてのバックグラウンド処理が正常に完了しました。”, vbInformation, “完了”
Exit Sub

ErrorHandler:
‘ — 6. 異常終了時のフェイルセーフ —
‘ エラーが発生しても、必ずCADの可視化とシステム変数の復元を行うこと
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー”

If Not acadApp Is Nothing Then
acadApp.Visible = True
On Error Resume Next
acadApp.SetSystemVariable “FILEDIA”, oldFileDia
acadApp.SetSystemVariable “CMDECHO”, oldCmdEcho
acadApp.SetSystemVariable “EXPERT”, oldExpert
End If

If Not acadDoc Is Nothing Then
acadDoc.Close False
End If

Exit Sub
End Sub

”’

”’ 図面個別の処理ロジック(サンプル)
”’

Private Sub ProcessDrawing(doc As AcadDocument)
‘ 例として、モデル空間の全エンティティを走査するなどの処理
Dim ent As AcadEntity
For Each ent In doc.ModelSpace
‘ 何らかの処理…
Next ent
End Sub

—

チーフアーキテクトからの実践的アドバイス

1. `EXPERT = 5` の破壊力に注意せよ
`EXPERT` 変数を `5` にすると、読み取り専用ファイルの強制上書きや、未定義のブロック定義に関する警告など、本来人間が立ち止まるべきアラートまですべてすっ飛ばして実行される。テスト環境で十分に挙動を検証し、意図しないデータ破損が起きないことを確認してから本番投入すること。
2. メモリリークの防止
ループ内で `Set acadDoc = Nothing` を怠ると、COMオブジェクトの参照が解放されず、バックグラウンドでAutoCADのプロセスがゾンビ化しメモリを食いつぶす。オブジェクトのライフサイクル管理はVBAにおける最大の生命線だ。
3. まずは `Visible = True` でデバッグしろ
最初から `Visible = False` で開発してはいけない。コードが完全に安定するまでは画面を表示させた状態で実行し、ダイアログがどこで発生するかを目視で確認するのがプロの鉄則だ。

この設計手法を取り入れれば、深夜残業して手作業で図面を開き直していた地獄のバッチ作業から完全に解放されるはずだ。あなたの開発する自動化ツールが、現場の圧倒的な武器となることを期待している。

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