【上級編】AutoCAD VBAの「待ち」を極める:外部参照インプレイス編集の同期制御術
こんにちは。AutoCADの自動化という荒野を旅するエンジニアの皆さん。
「マクロを実行したら、図面が外部参照編集中でエラーになった」「自動処理中にユーザーの操作が割り込んでクラッシュした」。そんな経験はありませんか?
実は、AutoCADのVBAで最も難しいのは「コードを書くこと」ではなく「AutoCADという生き物と呼吸を合わせること」です。今日は、外部参照のインプレイス編集(REFEDIT)という、システムにとって最も不安定な状態を安全にハンドリングする、プロフェッショナルな同期制御の手法を伝授します。
—
1. なぜ「外部参照編集」がバッチ処理を殺すのか?
AutoCADにおいて、外部参照のインプレイス編集(`REFEDIT`コマンド)は、図面データベース(`Database`)を一時的に「編集中」という特殊なロック状態にします。
このとき、AutoCADの内部では非常に複雑なオブジェクトの参照管理が行われており、外部からデータベースへアクセスしようとすると、システムが「今、編集用ロックがかかっているからアクセス拒否!」と例外(エラー)を吐くか、最悪の場合は強制終了します。
これを回避するために、「今、REFEDIT中かどうか?」を監視し、終わるまで静かに待機するガードレールを敷く必要があります。
—
2. 核心となるオブジェクトモデルの理解
AutoCAD VBAでこの状態を監視するには、`AcadDocument`オブジェクトの下にある `Database` プロパティを覗き込みます。
ここで重要なのは、`XRefEdit` という変数の状態です。
実は、AutoCADのシステム変数 `XEDIT` を監視するのが最も確実です。
- XEDIT = 0: 外部参照のインプレイス編集不可
- XEDIT = 1: 外部参照のインプレイス編集可能
- さらに重要なのは現在の編集状態: 現在進行形で編集しているかどうかは、システム変数 `REFEDITNAME` が空かどうかで判定します。
—
3. 実践:安全な同期待機コード
このコードは、バッチ処理を開始する前に必ず呼び出す「ゲートキーパー」として機能させます。
‘ — 安全な待機ロジック: WaitForRefEditFinish —
‘ 外部参照編集中であれば、ユーザーが編集を終了するまでループで待機します。
Public Sub WaitForRefEditFinish()
Dim app As AcadApplication
Set app = ThisDrawing.Application
Dim timeoutCounter As Long
timeoutCounter = 0
‘ REFEDITNAMEが空になるまで待機(最大1000回までチェック)
‘ 実務では必要に応じてループ制限を調整してください
Do While ThisDrawing.GetVariable(“REFEDITNAME”) <> “”
‘ ユーザーに待機中であることをステータスバーで通知
app.StatusBar = “外部参照編集中です。編集を終了してください…”
‘ 処理を一時停止し、AutoCADのイベントループを解放する
DoEvents
‘ 連続ループによるCPU負荷を防ぐための小休止
Sleep 500
timeoutCounter = timeoutCounter + 1
If timeoutCounter > 100 Then
MsgBox “外部参照の編集が終了されません。手動で終了してください。”, vbCritical
End ‘ バッチ処理を中断
End If
Loop
app.StatusBar = “準備完了。バッチ処理を開始します。”
End Sub
‘ Windows APIを使用してSleep関数を定義(DoEventsだけより安定します)
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If
—
4. コードの解説と「ハマりどころ」
1. `DoEvents` の魔法
VBAでループを回すと、AutoCADのGUIは「応答なし」になります。`DoEvents`を入れることで、AutoCADはOSからのイベント(ユーザーの操作や描画の更新)を受け取れるようになります。これがなければ、いつまで経ってもユーザーが「閉じる」操作を完了できず、デッドロックに陥ります。
2. `GetVariable` の重要性
`ThisDrawing.GetVariable(“REFEDITNAME”)` は、AutoCADの深層にあるシステム変数を直接参照する最も信頼できる手段です。`AcadDocument`のプロパティを直接いじるよりも、システム変数を監視する方が、AutoCADの「今の状態」を正確に反映します。
3. タイムアウト処理(安全装置)
無限ループは悪です。万が一のケース(システムエラーでロックが解除されない等)を想定し、必ずカウンタを設けてください。これは大規模なバッチ処理を組む際の「大人の作法」です。
—
最後に:自動化の先にあるもの
「コードが動けば良い」という段階から、「他人が使っても止まらないコード」を書く段階へ。ここをクリアすれば、あなたはもう立派なAutoCAD自動化エンジニアです。
AutoCAD VBAは古くからある言語ですが、そのオブジェクトモデルは非常に堅牢で、深く知れば知るほど新しい発見があります。この「同期制御」をマスターすることで、あなたのバッチ処理は現場の信頼を一気に獲得するはずです。
何か分からないことがあれば、いつでもまた聞きに来てくださいね。エンジニアとしての旅路を応援しています!
