【実務・中級編】【実務中級者向け】「読み取り専用」推奨ダイアログを自動で「はい」として処理するSendKeysとシステム変数の組み合わせ – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:図面オープン自動化の壁を突破せよ

AutoCADのバッチ処理や夜間の自動処理を組んでいて、もっとも絶望的な瞬間はいつだろうか?
そう、「ファイルを開く」という極めてプリミティブな処理の途中で、予期せぬダイアログが立ち上がり、プロセスの歯車が完全にフリーズした時だ。

中でも実務者を最も悩ませるのが、「読み取り専用で開きますか?」というあの忌々しい警告ダイアログである。

他のユーザーがすでに掴んでいる図面や、ネットワーク上の共有リソースをバッチで一括処理しようとした瞬間、AutoCADは処理を止め、ユーザーの「はい/いいえ」のクリックを待ち続ける。無人稼働させていたはずのサーバーの前で、翌朝に絶望した開発者が立ち尽くす……という光景は、現場では笑えない日常茶飯事だ。

今回は、このAutoCADの仕様の隙を突き、システム変数と泥臭いSendKeysを高度に調停させて「読み取り専用」ダイアログを完全にハックする実務的アプローチを伝授する。

—

なぜ「通常のオープン処理」ではバッチが止まるのか?

AutoCAD VBAにおいて、図面を開く基本構文は `Documents.Open` である。

‘ 通常の開き方(他者が使用中の場合にダイアログがポップアップする)
Dim doc As AutoCAD.AcadDocument
Set doc = ThisDrawing.Application.Documents.Open(“C:\Work\Sample.dwg”)

このコードの何が問題かといえば、AutoCADのドキュメントオープンは「モーダルな割り込み処理」を内包している点だ。ファイルが排他制御(ロック)されている検知した瞬間、AutoCADのコアエンジンはVBAの実行スレッドを一時停止させ、GUI上にダイアログを描画する。

VBAのランタイムはGUIスレッドの向こう側で完全にブロックされるため、コード側から「ダイアログが存在すること」を検知して制御を奪い返すことが、純粋なObjectARX/VBAのオブジェクトモデル単体では極めて困難になる。

誤ったアプローチ:エラートラップ(On Error)の過信

「ファイルが開けないならエラーになるはずだから、`On Error Resume Next` で無視すればいい」と考えていないだろうか?
甘い。排他ロックはVBAにとって「実行時エラー」ではない。AutoCADが対話型アプリケーションとして正常に警告を出しているだけなので、エラー番号は発生せず、ただひたすらユーザーの入力を待ち続ける無間地獄に突入するだけなのだ。

—

解決のアーキテクチャ:システム変数とSendKeysの協調制御

この壁を突破するには、「CADエンジンの警戒心を解くシステム変数」と「VBAからの非同期キーボード割り込み(SendKeys)」を緻密なタイミングでコンビネーションさせる必要がある。

ここでキーとなるのが以下の2点だ。

1. `SDI`(シングルドキュメントインターフェース)およびファイルロック機構の理解
2. `AppActivate` と `SendKeys` による、OSレベルのフォーカス制御

単純に `SendKeys` を叩くだけでは、どのウィンドウにキーが飛ぶか分からないため、バックグラウンド処理やマルチタスク環境では確実に暴走する。
「AutoCADのウィンドウを確実にアクティブ化し、ダイアログが出現する瞬間を狙い撃ちして `Y`(はい)を送り込む」という、極めてプラグマティック(実利主義)な設計が求められる。

—

プロダクションコード:完全自動「読み取り専用」オープナー

以下に提供するコードは、単なるスニペットではない。実際の現場で数千ファイルのバッチ処理を完遂するために、エラーハンドリングとウィンドウ制御のタイムラグを極限までチューニングしたプロダクションコードだ。

Option Explicit

‘ 外部API宣言:AutoCADウィンドウを確実にアクティブにするため
If VBA7 Then
Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

Public Sub OpenDrawingSafely_ReadOnly(ByVal FullPath As String)
Dim acadApp As AutoCAD.AcadApplication
Dim targetDoc As AutoCAD.AcadDocument
Dim fso As Object

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 1. ファイルの存在確認(大前提のガードバリデーション)
If Not fso.FileExists(FullPath) Then
MsgBox “指定されたファイルが存在しません: ” & vbCrLf & FullPath, vbCritical, “ファイルロスト”
Exit Sub
End If

Set acadApp = ThisDrawing.Application

On Error GoTo ErrorHandler

‘ 2. バックグラウンドでのキー送信に備え、AutoCADをアクティブ化
AppActivate acadApp.Caption

‘ 3. ダイアログを先回りして処理するためのSendKeys予約
‘ 「読み取り専用で開きますか?」に対して「はい (Yes)」となるよう “Y” または “{ENTER}” を送る
‘ ※環境の言語ロケール(日本語版)に依存するため、必要に応じて “%Y” (Alt+Y) や “{ENTER}” を調整
System.SetSystemVariable “FILEDIA”, 0 ‘ 必要に応じてファイルダイアログを抑制(今回はDocuments.Openなので基本OPENだが念のため)

‘ 非同期でダイアログが出るタイミングを見越し、キーをバッファに送り込む
‘ 複数回のEnterやYの送信は、ダイアログが出なかった場合に不要なコマンド実行を誘発するため厳に慎むこと
Application.VBARefPub ‘ ダミー処理ではなくタイミング調整用の余白

‘ 4. 読み取り専用強制オープンを狙うためのSendKeysアタック
‘ ダイアログが表示される瞬間に “Y” を叩きつける
SendKeys “Y”, True

‘ 5. ドキュメントのオープン実行
‘ 他者が開いている場合、ここで例のダイアログが発生し、直前のSendKeysがそれを即座に消化する
Set targetDoc = acadApp.Documents.Open(FullPath)

‘ 6. 開いたドキュメントが確実に読み取り専用になっているかの確認とログ出力
If targetDoc.ReadOnly Then
Debug.Print “[SUCCESS] 読み取り専用でオープンしました: ” & FullPath
Else
Debug.Print “[INFO] 通常モード(排他なし)でオープンしました: ” & FullPath
End If

‘ 必要に応じた処理をここに記述…

Exit Sub

ErrorHandler:
‘ 予期せぬエラーの捕捉
MsgBox “図面のオープン中に致命的なエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “自動化プロセス異常終了”

‘ SendKeysのバッファクリア(念のため)
Err.Clear
End Sub

—

現場で絶対に押さえておくべき「3つの実務的注意点」

このテクニックは非常に強力で、数々の現場のバッチ処理を救ってきた実績がある。しかし、OSやAutoCADのバージョン、環境差異に依存する側面があるため、以下のアーキテクトとしての警告を必ず胸に刻んでほしい。

1. 開発環境(VBE)のブレークポイント干渉に注意

`SendKeys` や `AppActivate` を使ったコードをデバッグする際、VBE(Visual Basic Editor)側でブレークポイントを挟むと、キーボードフォーカスがVBE側に奪われる。
その結果、本来AutoCADのダイアログに向かうはずの “Y” がVBEのエディタ上に打ち込まれ、コードが予期せぬ文字列で汚染されるという笑えない事故が起きる。デバッグ時は `F8` ステップ実行を多用せず、ロジックを固めてから一気に走らせるのが鉄則だ。

2. 多言語環境(ローカライズ)への配慮

日本語版AutoCADでは「読み取り専用で開きますか?」というダイアログのデフォルトボタンが「はい」であり、キーボードショートカットとして `Y`(Yes)あるいは `Enter` が有効である。
しかし、英語版(Read-only? -> Yes/No)や他の言語環境が混在するグローバル企業のエンドポイントでこのマクロを動かす場合、`SendKeys` の文字アサインを環境変数に応じて動的に切り替えるロジックをラップすべきだ。

3. データベース・外部連携時のトランザクション整合性

読み取り専用で開いた図面は、当然ながら `Save` メソッドでの上書き保存が拒絶される。
もしこの自動化ツールの目的が「大量の図面から一括で属性(Attributes)やブロック情報を抽出し、外部DBにインデックス化すること」であれば、読み取り専用で開くことは「安全かつ理想的な挙動」である。逆に、図面をプログラム側で改変して保存し直す必要がある場合は、そもそも排他制御がかかっているファイルを強行突破すべきではない。ユースケースの主目的に応じて、このコードを適用するかどうかを厳格にジャッジせよ。

—

総括:泥臭いハックを「洗練されたシステム」に昇華させろ

APIが用意されていない挙動や、UIの割り込みを伴うレガシーなダイアログに対して、オブジェクト指向のきれいごとだけで立ち向かっても、実務の自動化は絶対に完遂できない。

システム変数による環境の統御と、OSレベルのフォーカス制御(SendKeys)を組み合わせたこのアプローチは、一見すると「泥臭いハック」に見えるかもしれない。しかし、「絶対にバッチを止めない」というエンジニアの強い意志を具現化したコードこそが、現場の生産性を爆発的に引き上げる真のソリューションである。

あなたのデスクトップ上のAutoCADが、明日から夜間休日を問わず、誰の手を借りることもなく静かに、そして確実に図面群を咀嚼し続けることを約束しよう。

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