AutoCAD VBAを掌握せよ:ActiveDocumentという「罠」を回避し、堅牢な自動化を実現する極意
AutoCADの自動化において、最も初歩的かつ致命的なミスが、`ThisDrawing` や `ActiveDocument` への無批判な依存だ。
「とりあえず動けばいい」というコードは、単一図面環境では機能する。しかし、実務の現場で複数の図面が開きっぱなしになっている環境では、突如として別の図面にデータを書き込み、顧客に納品する図面を破壊する「時限爆弾」と化す。
今日は、AutoCAD VBAのオブジェクトモデルを正しく理解し、複数図面環境でも意図通りに動作する「真にプロフェッショナルな」オブジェクト取得法を授ける。
—
1. なぜ `ActiveDocument` は危険なのか?
AutoCADのオブジェクトモデルにおいて、`ActiveDocument` は「現在、ユーザーが画面上でアクティブにしている図面」を指すポインタに過ぎない。
ユーザーがマクロの実行中に誤って別のタブをクリックしたり、バックグラウンドで別のプロセスが割り込んだりした瞬間、`ActiveDocument` が指す先は変わる。あなたのコードは、操作対象を決定する権限をユーザーのクリック一つに委ねているのだ。 これは業務自動化ツールとしては失格である。
—
2. 堅牢なオブジェクト取得:3つの鉄則
複数図面環境で事故を防ぐためには、以下の手順を徹底せよ。
1. Applicationオブジェクトを起点にする: `ThisDrawing` ではなく、`AcadApplication` から図面を明示的に取得する。
2. インデックスではなく名前で特定する: ファイル名やパスをキーにして、目的のドキュメントがメモリ上に存在するかを確認する。
3. 例外処理(エラーハンドリング)の強制: 図面が開いていない、または読み取り専用である場合を想定し、必ず `Err` オブジェクトを制御下に置く。
—
3. 実践:プロダクションレベルのコード
以下は、特定の図面名(フルパスまたはファイル名)を指定して、確実にそのオブジェクトを捕捉する関数だ。このコードを君のライブラリのコアに据えろ。
‘ ———————————————————
‘ 指定した名前のドキュメントを確実に取得する関数
‘ @param targetName 取得したい図面名(またはフルパス)
‘ @return 捕捉したAcadDocumentオブジェクト
‘ ———————————————————
Public Function GetDocumentByName(ByVal targetName As String) As AcadDocument
Dim doc As AcadDocument
Dim app As AcadApplication
Set app = ThisDrawing.Application
‘ 全ての開かれている図面を走査する
For Each doc In app.Documents
‘ フルパスで一致するか、ファイル名のみで一致するかを確認
If InStr(1, doc.FullName, targetName, vbTextCompare) > 0 Or _
InStr(1, doc.Name, targetName, vbTextCompare) > 0 Then
Set GetDocumentByName = doc
Exit Function
End If
Next doc
‘ 見つからなかった場合は明示的にエラーを発生させる
Err.Raise vbObjectError + 1001, “GetDocumentByName”, “図面 ‘” & targetName & “‘ が開かれていません。”
End Function
‘ — 利用例 —
Public Sub ProcessMyDrawing()
On Error GoTo ErrorHandler
Dim targetDoc As AcadDocument
Set targetDoc = GetDocumentByName(“Project_A_Layout.dwg”)
‘ ここからはActiveDocumentではなく、確実に取得したtargetDocを操作する
targetDoc.Activate
MsgBox “現在操作中の図面: ” & targetDoc.Name
Exit Sub
ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub
—
4. 開発リーダーからの「極限の知見」
オブジェクトの寿命(ライフサイクル)を意識せよ
VBAで `Set obj = …` としたとき、それは参照カウンタを上げている。特に外部DB連携やExcelとの連携を行う際、図面を閉じる処理(`doc.Close`)を忘れると、メモリリークが発生しAutoCAD自体が不安定になる。「開いたら閉じる」というスコープ管理を徹底せよ。
なぜ `ThisDrawing` を避けるべきか
`ThisDrawing` は便利だが、これはコードが書かれている図面ファイルそのものに依存する。将来的にテンプレート化したり、別ファイルからツールを呼び出したい場合、途端に拡張性が死ぬ。`Application` を頂点とした階層構造を常に意識するだけで、君のコードの質は劇的に向上する。
—
結論:自動化は「信頼」の上に成り立つ
業務自動化の目的は、単に「楽をすること」ではない。「ミスをゼロにすること」だ。
ユーザーの操作ミスを「想定外」として放置するのではなく、コード側で「操作を強制的に特定する」設計に切り替えること。これが、伝説的な自動化エンジニアと、ただのスクリプトキディの決定的な差である。
今日から君のすべてのコードで、`ActiveDocument` という安易な甘えを捨て、明示的なオブジェクト管理を実装せよ。それが、堅牢な業務システムを構築するための第一歩だ。
