AutoCAD VBAの深淵:AcadDocumentを制し、メモリを支配する
AutoCAD APIの入り口である`AcadDocument`の作成と図形描画。多くのチュートリアルは「動けば良い」コードを提示するが、我々が扱うのは24時間稼働の設計自動化パイプラインや、数千枚の図面を処理するバッチシステムだ。
ここでは、単なるHello Worldを超え、メモリリークを根絶し、レガシー環境でいかに堅牢なコードを構築するか、その「極限の知見」を共有する。
—
1. ドキュメント作成の真実:Applicationの背後に潜む罠
新規図面を作成する際、安易に`Documents.Add`を呼び出してはならない。AutoCADのオブジェクトモデルにおいて、`Application`はCOMサーバーの頂点であり、ここでのリソース管理ミスはAutoCADそのもののクラッシュを招く。
‘ 【警告】AcadDocumentは常に明示的な参照を持つこと
Public Sub CreateDocumentSecurely()
Dim acadApp As AcadApplication
Dim newDoc As AcadDocument
‘ 実行中のAutoCADに接続(Late Binding推奨:バージョン非依存のため)
Set acadApp = GetObject(, “AutoCAD.Application”)
‘ テンプレートを指定した明示的な作成
‘ “acadiso.dwt”等のフルパスを渡すのがベストプラクティス
Set newDoc = acadApp.Documents.Add(“acadiso.dwt”)
‘ ここで描画処理を行う
Call DrawGeometry(newDoc)
‘ 重要な知見:オブジェクトの解放
‘ VBAはガベージコレクションが脆弱なため、Set Nothingは必須
Set newDoc = Nothing
Set acadApp = Nothing
End Sub
—
2. ModelSpaceへのアクセスとメモリの最適化
`ModelSpace`は図形オブジェクトの集合体(Collection)だが、ここへのアクセス頻度はパフォーマンスに直結する。ループ内での`ThisDrawing.ModelSpace`呼び出しは、COMマーシャリングのオーバーヘッドを増大させる。
最適化の鉄則:
- 変数へのキャッシュ: `ModelSpace`を一度オブジェクト変数にセットし、その参照を使い回せ。
- レイヤーとプロパティ: 図形作成前に必ず画層(Layer)や線種(Linetype)の存在を確認せよ。存在しない画層への書き込みは例外を投げる。
Private Sub DrawGeometry(ByRef targetDoc As AcadDocument)
Dim mSpace As AcadModelSpace
Dim lineObj As AcadLine
Dim circleObj As AcadCircle
Dim startPoint(0 To 2) As Double
Dim endPoint(0 To 2) As Double
Dim center(0 To 2) As Double
Set mSpace = targetDoc.ModelSpace
‘ 線分の作成:座標配列の定義
startPoint(0) = 0: startPoint(1) = 0: startPoint(2) = 0
endPoint(0) = 100: endPoint(1) = 100: endPoint(2) = 0
Set lineObj = mSpace.AddLine(startPoint, endPoint)
‘ 円の作成
center(0) = 50: center(1) = 50: center(2) = 0
Set circleObj = mSpace.AddCircle(center, 25)
‘ 描画後の更新
targetDoc.Regen acActiveViewport
‘ 即時解放
Set circleObj = Nothing
Set lineObj = Nothing
Set mSpace = Nothing
End Sub
—
3. レガシー環境を生き抜くための防衛的プログラミング
長年運用されてきたシステムでは、AutoCADのバージョン混在や、ユーザーによる強制終了が常にリスクとなる。
Windows APIによるウィンドウハンドルの監視
VBA単体では、AutoCADが「コマンド実行中」か「ユーザー待機中」かを完璧に判定できない。必要に応じて`User32.dll`の`FindWindow`や`GetForegroundWindow`を呼び出し、システムの状態をセーフガードせよ。
システム間連携の勘所
もし外部システム(DBやExcel)からAutoCADを制御するなら、以下の3点に魂を込めろ。
1. Error Handlingの徹底: `On Error Resume Next`を多用するのは三流の証だ。エラー発生時に`AcadDocument.Close False`を呼び出し、ゾンビプロセスを作らせないこと。
2. 遅延バインディング(Late Binding)の活用: `Dim acadApp As Object`とすることで、AutoCAD 2018から2025まで、コードを書き換えることなく単一のバイナリで対応可能になる。
3. Undoマークの活用: `Document.StartUndoMark`と`EndUndoMark`で囲むことにより、プログラムによる一連の操作を「1つの取り消し単位」に収めろ。ユーザー体験(UX)を損なわないことは、システムエンジニアとしての矜持である。
—
アーキテクトからの提言
AutoCAD VBAはレガシーと言われるが、その真の力は「図面という巨大なデータ構造を、メモリ上で直接叩ける」という点にある。
APIリファレンスをなぞるだけでは、AutoCADの真のパワーは引き出せない。オブジェクトの生存期間を意識し、COMのオーバーヘッドを削ぎ落とし、異常系を想定した堅牢なエラーハンドリングを実装せよ。
コードはただ動けばいいのではない。「誰が、いつ、どんな環境で実行しても、必ず同じ結果を返す」こと。それこそが、伝説のエンジニアに求められる唯一の指標である。
