AutoCAD VBAの深淵:オブジェクト走査の「作法」とメモリマネジメントの真実
AutoCAD VBAは、現代の .NET API や ObjectARX に比べれば「レガシー」の烙印を押されがちだ。しかし、システム管理者や現場のエンジニアにとって、この言語が持つ即時性と、AutoCADのコアプロセスに直接触れられるという特性は、今なお強力な武器である。
多くの初心者が陥る罠は、`ModelSpace`を単なる配列として扱い、メモリを浪費し、処理を停滞させることだ。今回は、ただ「動く」コードではなく、「大規模図面でも息切れしない」プロフェッショナルの走査手法を伝授する。
—
1. 効率的なオブジェクト走査の設計図
AutoCADのオブジェクトモデルにおいて、`ModelSpace`はデータベースだ。これをループ処理する際、最も避けなければならないのは「不必要なオブジェクトのインスタンス化」である。
以下のコードは、条件に合致するオブジェクトを抽出し、ログとして出力するアーキテクトの実装例である。
Option Explicit
‘ 伝説的なエンジニアは、定数をハードコーディングしない
Private Const TARGET_LAYER As String = “WALL_MAIN”
Private Const TARGET_COLOR As Integer = 1 ‘ Red
Public Sub ExtractTargetObjects()
Dim doc As AcadDocument
Dim space As AcadBlock
Dim ent As AcadEntity
Set doc = ThisDrawing
‘ 走査対象:モデル空間または現在のアクティブなレイアウト
Set space = doc.ModelSpace
‘ 処理の高速化:画面更新を止める
doc.Application.BeginCommand “$UNDO_MARK”
For Each ent In space
‘ オブジェクトのフィルタリング
‘ プロパティへのアクセスは最小限に。評価順序を考慮する。
If ent.Layer = TARGET_LAYER And ent.Color = TARGET_COLOR Then
‘ ここでビジネスロジックを実行
Debug.Print “Found: ” & ent.ObjectName & ” / Handle: ” & ent.Handle
End If
Next ent
‘ 終了処理
Set ent = Nothing
Set space = Nothing
Set doc = Nothing
End Sub
なぜこの実装が重要なのか
- イベント抑制: `BeginCommand` 等で処理をラップし、画面の再描画負荷を抑制する。
- 明示的な解放: VBAのガベージコレクションは非常に遅い。`Set ent = Nothing` は、ループ内ではなくとも、スコープ終了時には必須の儀式だ。これを行わないコードは、大規模図面でのメモリリークの元凶となる。
—
2. パフォーマンスの限界を突破する「SelectionSets」の活用
もし走査対象が数万要素を超える場合、単純な `For Each` は死を意味する。その場合、SelectionSets を使用すべきだ。これはAutoCADの内部データベースエンジンである `AcDb` に直接クエリを投げる手法に近く、VBA層でのループ処理を圧倒的に短縮できる。
Public Sub HighPerformanceFilter()
Dim sset As AcadSelectionSet
Dim filterType(0) As Integer
Dim filterData(0) As Variant
‘ 既存の選択セットをクリア
On Error Resume Next
ThisDrawing.SelectionSets(“MyFilter”).Delete
On Error GoTo 0
Set sset = ThisDrawing.SelectionSets.Add(“MyFilter”)
‘ DXFグループコードでフィルタリング(これが高速化の鍵)
filterType(0) = 8: filterData(0) = TARGET_LAYER
‘ 選択セットに条件合致オブジェクトを格納
sset.Select acSelectionSetAll, , , filterType, filterData
‘ あとは格納されたオブジェクトを処理するだけ
Dim i As Long
For i = 0 To sset.Count – 1
‘ 処理
Next i
sset.Delete
End Sub
この「DXFグループコード」によるフィルタリングこそが、シニアエンジニアが現場で重宝する技術だ。`For Each` で全オブジェクトをメモリに展開するのではなく、AutoCADのエンジン側で抽出させる。この「境界線」を理解しているか否かが、エンジニアの格を分ける。
—
3. Windows APIによる「極限の制御」
社内システム連携やUI制御において、標準のVBAだけでは手が届かない領域がある。例えば、処理中にAutoCADのタイトルバーを書き換えたり、メモリ使用量を監視してアラートを出すようなケースだ。
`Declare` ステートメントを用いて `Kernel32.dll` を叩くことは、現代ではあまり推奨されないかもしれない。しかし、レガシー環境の保守において、プロセスIDからメモリ占有量を特定するような場面では、今なお最強の手段だ。
‘ プロセス情報を取得するためのWindows API例
Private Declare PtrSafe Function GetCurrentProcessId Lib “kernel32” () As Long
このように、VBAを「AutoCAD専用の言語」と見なすのではなく、「OSとCADを仲介する統合開発環境」として捉えること。それが、真に価値ある業務自動化システムを構築するための第一歩である。
—
最後に:コードは「生き物」である
あなたが書いたコードは、あなたがいなくなった後も、数年間にわたって誰かのPCで走り続ける可能性がある。
- 変数名は意図を語らせる
- エラー処理は逃げ道ではなく、防波堤にする
- そして何より、CADのデータベース構造を常に意識する
AutoCAD VBAは、決して古臭い技術ではない。CADの心臓部を直接操る、もっともシンプルで強力なインターフェースだ。この設計指針を胸に、現場の課題を一つずつ、エレガントに解決していってほしい。
健闘を祈る。
