こんにちは!AutoCAD VBAの荒波へようこそ。チーフアーキテクトの私です。
現場でバリバリとAutoCADを自動化していると、必ずと言っていいほど直面する恐怖の瞬間があります。それは「複数の図面を開いているときに、意図しない画面へマクロが暴走し、勝手に線を書き殴っていくホラー現象」です。
「あれっ、こっちの図面を処理したかったのに、裏で開いていた別の図面に書き込まれてる……!」
そんな冷や汗をかいた経験はありませんか?
今回は、複数起動するAutoCADの群雄割拠の中から、あなたが「今、本当に操作したい特定のインスタンス」を確実に掴み取り、安全に制御するための極意を伝授します。
ここをクリアすれば、あなたのAutoCAD VBAのスキルは「おもちゃのマクロ」から「現場で信頼されるプロの自動化ツール」へと劇的に進化しますよ。ついてきてくださいね!
—
1. なぜ複数起動のAutoCADで「暴走」が起きるのか?
私たちが普段何気なく使っている `CreateObject` や `GetObject`、あるいは `ThisDrawing`。これらは非常に便利な反面、「今、アクティブになっている(あるいはOSが適当に選んだ)AutoCAD」を掴んでしまいます。
Windowsのタスクマネージャーを開いてみてください。`acad.exe` というプロセスが、起動している図面の数だけ(あるいはセッションごとに)動いていますよね。
VBAから「AutoCADのアプリケーションをくれ!」と頼んだとき、OSは「どれのこと?」と迷ってしまいます。その結果、意図しないプロセスを操作してしまうのです。
これを防ぐためには、「今、自分が動かしているVBAが、どのプロセスID(StatusId / Process ID)のAutoCADと結びついているか」を明確に把握し、識別しなければなりません。
—
2. 秘密兵器:`AcadApplication.StatusId` とは?
ここで登場するのが、今回の中核である `StatusId`(※厳密にはCOMのプロセスID、PIDを指します)です。
AutoCADのアプリケーションオブジェクトには、そのプロセスを一意に識別するためのIDが割り振られています。これを利用することで、「お前はPID: 12345だな?よし、お前を操作するぞ」と、ピンポイントで指定が可能になるのです。
思考の図解:複数プロセスの世界
[ Windows OS の世界 ]
┣ acad.exe (プロセスID: 4102) ─── [図面A.dwg]
┣ acad.exe (プロセスID: 8820) ─── [図面B.dwg] ★今回操作したいターゲット!
┗ Excel / VBA
┗ 「PID: 8820 の AutoCAD よ、私と接続せよ!」
この「名指しでの通信」を実現するための具体的なコードを見ていきましょう。
—
3. 実践コード:特定のAutoCADインスタンスを特定して制御する
以下のコードは、現在立ち上がっているAutoCADのプロセスを列挙し、その中から特定の条件(あるいは手動で指定したID)に合致するインスタンスを確実にキャッチするためのサンプルです。
ExcelのVBE(Visual Basic Editor)などに貼り付けて試してみてください。
Option Explicit
‘ Windows APIを使用して、実行中のプロセスからAutoCADを特定する高度なアプローチもありますが、
‘ まずは基本となるアプリケーションオブジェクトの挙動とPIDの概念を押さえましょう。
Sub GetSpecificAutoCADInstance()
On Error GoTo ErrorHandler
Dim acadApp As AcadApplication
Dim isAppRunning As Boolean
isAppRunning = False
‘ すでに起動しているAutoCADのアプリケーションオブジェクトを取得を試みる
‘ ※注意: GetObject(“”, “AutoCAD.Application”) は「現在アクティブなインスタンス」を拾います
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application.24”) ‘ バージョンに応じて調整 (例: AutoCAD 2023なら .24等)
If Err.Number <> 0 Then
‘ 見つからない場合は新規起動
Err.Clear
Set acadApp = CreateObject(“AutoCAD.Application”)
isAppRunning = False
Else
isAppRunning = True
End If
On Error GoTo ErrorHandler
‘ 可視化する
acadApp.Visible = True
‘ 【重要】ここに注目!現在掴んでいるAutoCADのプロセスID(StatusId相当)を確認する
‘ ※VB.NET等のAPI環境では StatusId プロパティが直に使えますが、
‘ VBAのCOM連携においては、ウィンドウハンドル(HWND)やプロセスIDを組み合わせて一意性を担保します。
MsgBox “現在制御しているAutoCADのバージョン: ” & acadApp.Name & vbCrLf & _
“バージョン番号: ” & acadApp.Version & vbCrLf & _
“ウィンドウハンドル(HWND): ” & acadApp.HWND, _
vbInformation, “インスタンス特定完了”
‘ 安全な図面操作の開始
Dim acadDoc As AcadDocument
Set acadDoc = acadApp.ActiveDocument
If Not acadDoc Is Nothing Then
MsgBox “操作対象の図面名: ” & acadDoc.Name, vbInformation, “安全確認OK”
‘ ここに実際の自動化処理を記述します
Else
MsgBox “現在、アクティブな図面が開かれていません。”, vbExclamation
End If
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
—
4. 現場で陥りやすい罠と回避の極意
初心者のうちは、次の罠にハマりがちです。ここを知っておくだけで、現場でのトラブルシューティング能力がグッと跳ね上がります。
罠1: `GetObject` が意図しないインスタンスを掴む
複数のAutoCADが立ち上がっている状態で `GetObject(, “AutoCAD.Application”)` を実行すると、OSが最後にフォーカスを持っていた(あるいは最初に生成された)インスタンスを気まぐれに返してきます。
これを避けるためには、あらかじめ対象の図面ファイルを `Documents.Open` で明示的に開き、その戻り値から `Application` オブジェクトを逆引きするのが最も確実です。
‘ 【推奨アプローチ】パスを指定して開き、そのドキュメントから親アプリケーションを特定する
Dim targetDoc As AcadDocument
Dim targetApp As AcadApplication
‘ 特定のファイルを明示的に開くことで、どのインスタンスで動いているかを完全にコントロールする
Set targetDoc = Documents.Open(“C:\Work\MyDrawing.dwg”)
Set targetApp = targetDoc.Application
‘ これで targetApp は確実に 「MyDrawing.dwg」 を抱えているインスタンスを指します!
罠2: バージョン違いのCOM指定ミス
AutoCADは毎年バージョンアップするため、プログラムID(ProgID)が変わります。
- AutoCAD 2024 なら `AutoCAD.Application.24.1` のように内部的なバージョンサフィックスが存在します。
- 汎用的な `AutoCAD.Application` を使うと、PCに複数インストールされている場合に予期せぬバージョンのAutoCADが起動することがあるため注意が必要です。
—
5. おわりに:プロのエンジニアへの第一歩
お疲れ様でした!今回は「複数のAutoCADが起動している中から、特定のインスタンスを確実に制御する」という、実務で絶対に避けて通れないテーマについて解説しました。
「なんとなく動くコード」から「意図通りに確実に制御できるコード」への脱皮。
ここをクリアできたあなたなら、もうマクロの記録のリーマンから、現場を牽引する自動化エンジニアの仲間入りです。
安全で堅牢なAutoCAD VBAライフを、心から応援しています。それでは、次の現場でお会いしましょう!
