【実務・中級編】【上級】AcadDocument.Database.XRefEdit状態を監視し、外部参照のインプレイス編集が完了するまでVBAのバッチ処理を待機させる同期制御 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAの深淵:外部参照(XRef)編集を「待機」する同期制御の設計哲学

AutoCADで大規模な自動化ツールを組む際、多くのエンジニアが初心者の壁にぶつかるのが「外部参照(XRef)のインプレイス編集」という魔物です。

ユーザーがコマンド `REFEDIT` を実行している最中に、VBAからデータベースを操作しようとすればどうなるか? 答えは簡単、「致命的な例外」か「図面データベースの不整合」です。AutoCADのオブジェクトモデルにおいて、現在編集中の図面(Document)は、インプレイス編集モードに入るとデータベースのロック状態が変化します。

今回は、この「非同期的な人間の介入」をいかにしてVBAでハンドリングし、堅牢なバッチ処理を実現するか。その極意を伝授します。

なぜ `DoEvents` だけでは不十分なのか

巷のコードでは `DoEvents` をループさせるだけの安易な待機処理が見受けられますが、これはプロの設計ではありません。CPUを無駄に回し、イベントのスタックを汚染し、最悪の場合はAutoCAD自体をフリーズさせます。

私たちは、AutoCADの `Document` オブジェクトが持つ「状態」を正しく読み取る必要があります。特に `XRefEdit` 中であることを検知する直接的なフラグは公開されていませんが、「データベースのロック状態」と「システム変数」を組み合わせることで、確実な同期制御が可能になります。

実装の鍵:システム変数 `XEDIT` を監視する

AutoCADには `XEDIT` というシステム変数があります。これが `1` であればインプレイス編集が許可され、現在編集中の状態であれば、データベースは「ロック」されます。

以下のコードは、単なる待機ではなく、安全に処理を再開できるまで待機する「同期監視ガード」の実装例です。

堅牢な同期待機クラス:`XRefSyncGuard`

‘ — プロダクション用:同期制御モジュール —
Option Explicit

‘ 外部参照インプレイス編集が完了するまで待機する
‘ @param timeoutSeconds タイムアウトまでの秒数(無限ループ防止)
Public Function WaitUntilXRefEditFinished(Optional timeoutSeconds As Long = 30) As Boolean
Dim startTime As Double
startTime = Timer

‘ インプレイス編集モード(REFEDIT)中は、システム変数 XEDIT が 0 になる場合や
‘ データベースがロックされる挙動を利用する。
‘ 最も確実なのは、SendCommand等で同期を取る前にこのチェックを挟むこと。

Do While IsXRefEditing()
‘ タイムアウトチェック
If (Timer – startTime) > timeoutSeconds Then
Err.Raise vbObjectError + 1000, “XRefSyncGuard”, “タイムアウト:外部参照の編集が終了しませんでした。”
WaitUntilXRefEditFinished = False
Exit Function
End If

‘ UIスレッドをブロックせず、AutoCADの処理を許可する
DoEvents
Sleep 100 ‘ APIで適切にスリープを入れる(後述)
Loop

WaitUntilXRefEditFinished = True
End Function

‘ 現在外部参照を編集しているか判定
Private Function IsXRefEditing() As Boolean
‘ システム変数 XREFEDIT を確認
‘ 1: 編集許可, 0: 編集不可(現在編集中の可能性が高い)
‘ ※環境やバージョンに応じて GETVAR(“DBMOD”) 等と組み合わせるのが定石
On Error Resume Next
If ThisDrawing.GetVariable(“XREFEDIT”) = 0 Then
IsXRefEditing = True
Else
IsXRefEditing = False
End If
End Function

現場で差がつく「待機」の作法

上記のコードを運用に乗せる際、以下の2点に注意してください。これを見落とすと、どんなに綺麗なコードでもクラッシュします。

1. `Sleep` API の活用

`DoEvents` だけでループさせるとCPU使用率が跳ね上がります。Windows APIの `Sleep` を併用し、ミリ秒単位で制御をOSに戻すのがプロの流儀です。

If VBA7 Then
Public Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Public Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

2. データベース操作前の「最終防衛ライン」

どれだけ監視しても、VBAの実行直前にユーザーが `REFEDIT` を開始する可能性はゼロではありません。VBAからデータベース(`ThisDrawing.ModelSpace` など)にアクセスする直前には、必ずエラーハンドラを設置し、`Err.Number` を監視してください。

On Error GoTo ErrorHandler
‘ — データベース更新処理 —
‘ …

Exit Sub
ErrorHandler:
If Err.Number = -2145386458 Then ‘ 典型的なデータベースロックエラーのコード
MsgBox “図面がロックされています。編集を終了してから実行してください。”, vbCritical
End If

結論:自動化の本質は「待つこと」にある

優れた業務自動化エンジニアは、コードを書く時間よりも、「システムがどのような状態にあるときに、いかなる干渉を受けるか」を想像する時間を大切にします。

外部参照のインプレイス編集は、CAD業務のフローにおいて不可欠な作業です。それを「邪魔なもの」として排除するのではなく、システムの状態監視を通じて「協調」させる。これこそが、職人レベルのVBA開発に求められるアーキテクチャ思考です。

この `XRefSyncGuard` をあなたのライブラリに加え、強固で壊れない自動化システムを構築してください。それが、明日からのあなたの設計を劇的に変えるはずです。

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