【テクニカル・上級編】【実務中級】AutoCAD VBAで図面内の全ブロック参照(Block Reference)を検索し、属性値に基づいてフィルタリングする – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAの深淵:ブロック属性の高速抽出とメモリ管理の極意

AutoCADのAPIにおいて、`ModelSpace`や`PaperSpace`を漫然とループさせていないか?
数万のエンティティを抱える図面で、全検索をかけてフリーズするようなコードは、プロフェッショナルの仕事ではない。

今回は、AutoCAD VBAにおける「ブロック参照の高速抽出と属性フィルタリング」という、実務の現場で最も頻出する課題に対し、伝説的なアーキテクトの視点からその最適解を提示する。

1. なぜ「力技」ではいけないのか

AutoCADのオブジェクトモデルにおいて、`ModelSpace`を`For Each`で回すのは、初心者が犯す最大の過ちだ。特に、入れ子構造になったブロックや、複雑な属性を持つ図面では、COMインターフェースを介したアクセスは驚くほど重い。

真に効率的なコードを書くためには、以下の3点を徹底しなければならない。

1. オブジェクトの明示的解放: VBAのガベージコレクションに依存してはならない。`Nothing`を代入し、メモリを強制的に解放する。
2. 遅延バインディングを避ける: 型定義を明確にし、コンパイル時に最適化を促す。
3. 属性アクセスを最小化する: `GetAttributes`メソッドは配列を返すため、何度も呼び出すとメモリリークの温床になる。一度の呼び出しで処理を完結させる。

2. 実装:高速フィルタリングエンジン

以下のコードは、指定したブロック名と属性値を検索し、該当するエンティティを`Collection`に格納する。実務レベルでは、これをベースに修正を行うのが定石だ。

Option Explicit

‘ 伝説的なエンジニアは、定数をハードコードしない
Private Const TARGET_BLOCK_NAME As String = “PART_INFO_BLOCK”
Private Const TARGET_TAG_NAME As String = “PART_ID”
Private Const TARGET_VALUE As String = “1001-A”

Public Sub ExtractTargetBlocks()
Dim acadDoc As AcadDocument
Dim blkRef As AcadBlockReference
Dim ent As AcadEntity
Dim attrArr As Variant
Dim i As Long
Dim foundCount As Long

Set acadDoc = ThisDrawing
foundCount = 0

‘ ModelSpaceを効率的に走査
For Each ent In acadDoc.ModelSpace
If TypeOf ent Is AcadBlockReference Then
Set blkRef = ent

‘ 名前の一致チェック(大文字小文字を区別しない)
If StrComp(blkRef.Name, TARGET_BLOCK_NAME, vbTextCompare) = 0 Then
‘ 属性値の取得(HasAttributesで事前確認を行う)
If blkRef.HasAttributes Then
attrArr = blkRef.GetAttributes

For i = LBound(attrArr) To UBound(attrArr)
‘ タグ名と値の照合
If StrComp(attrArr(i).TagString, TARGET_TAG_NAME, vbTextCompare) = 0 Then
If StrComp(attrArr(i).TextString, TARGET_VALUE, vbTextCompare) = 0 Then
Debug.Print “Found: Handle=” & blkRef.Handle
foundCount = foundCount + 1
‘ 必要に応じて選択セットに追加などを行う
End If
End If
Next i
End If
End If
End If

‘ 毎イテレーションごとにオブジェクトを解放
Set blkRef = Nothing
Set ent = Nothing
Next ent

MsgBox “検索完了: ” & foundCount & “個のブロックが見つかりました。”, vbInformation
End Sub

3. レガシーシステムを掌握する技術的知見

Windows APIによる制御(応用編)

もしAutoCADのウィンドウが「応答なし」になるような巨大な図面を扱う場合、`DoEvents`を安易に使うのは避けろ。代わりにWindows APIの`Sleep`関数を用いて、CPUの負荷をコントロールしつつ、メッセージキューを処理させるのがシニアの作法だ。

If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

パフォーマンスを極限まで高めるには

1. SelectionSetsの活用: `ModelSpace`を全ループするのではなく、フィルタ付きの`SelectionSet`を作成せよ。`DxfCode`を使用して、AutoCADの内部エンジンでフィルタリングさせる方が、VBA側で判定するよりも10倍以上高速だ。
2. Undoブロックの最小化: 一括処理の前後に`StartUndoMark`と`EndUndoMark`を配置せよ。これにより、Undoスタックの肥大化を防ぎ、システム全体の安定性を確保できる。

結論

AutoCAD VBAはレガシーではない。強力なAPIを正しく制御すれば、現代のどの最新ツールよりも高速に図面を制御できる「最強の自動化環境」だ。

オブジェクトのライフサイクルを管理し、メモリを枯渇させず、CPUに無駄な負荷をかけない。この姿勢こそが、システム管理者が抱える「不安定なマクロ」という爆弾を解除する唯一の道である。

次は、このデータを外部DB(SQL Server)と連携させるパイプライン構築について議論しようか。準備ができたらまた来い。

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