【テクニカル・上級編】【初心者向け】図面内の全オブジェクトを走査し、特定のプロパティ(画層、色、線種)を持つオブジェクトを抽出する – AutoCAD VBA解析バイブル

スポンサーリンク

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の心臓部を直接操る、もっともシンプルで強力なインターフェースだ。この設計指針を胸に、現場の課題を一つずつ、エレガントに解決していってほしい。

健闘を祈る。

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