AutoCAD VBAの深淵:ブロック参照の「真の」フィルタリング手法
AutoCADの業務自動化において、ブロック参照(`AcadBlockReference`)の操作は避けて通れない登竜門だ。しかし、多くのエンジニアが陥る罠がある。それは「図面内の全エンティティをループで回し、`If TypeOf` で判定し続ける」という、極めて低効率なコードだ。
図面規模が数万オブジェクトを超えた瞬間、そのコードはCPUを食いつぶし、ユーザーをイライラさせるだけの「負債」に変わる。
本稿では、プロフェッショナルとして、「なぜその手法がNGなのか」を解き明かし、実務で絶対に壊れない、かつ爆速で動作する設計手法を授ける。
—
1. なぜ「全エンティティ走査」は悪手なのか
`ModelSpace` を `For Each` で回すのは、図面が小さい時だけの甘えだ。AutoCADのオブジェクトモデルにおいて、レイアウト、ペーパー空間、ブロック定義内のネストされたオブジェクトまで考慮すれば、再帰処理やコレクションの管理が複雑化し、メンテナンス性は崩壊する。
真のプロが行うべきアプローチは「SelectionSetsの活用」と「最適化されたフィルタリング」である。
2. 堅牢な実装:SelectionSetsを用いた高速抽出
`SelectionSet` を使う最大のメリットは、AutoCADの内部エンジンが持つ強力なフィルタリング機能を活用できる点にある。これにより、VBA側で逐一判定を行うオーバーヘッドを劇的に削減できる。
プロダクションコード例
このコードは、指定したブロック名かつ、特定の属性タグを持つものを抽出する実用的なテンプレートだ。
Option Explicit
‘ ———————————————————
‘ 目的: 指定したブロック名の属性値を高速にフィルタリングする
‘ ———————————————————
Public Sub FilterBlocksByAttribute()
Dim sset As AcadSelectionSet
Dim filterType(0) As Integer
Dim filterData(0) As Variant
Dim blkRef As AcadBlockReference
Dim attribs As Variant
Dim i As Long
‘ 1. SelectionSetの初期化 (既存があれば削除する鉄則)
On Error Resume Next
ThisDrawing.SelectionSets.Item(“MyTempSet”).Delete
On Error GoTo 0
Set sset = ThisDrawing.SelectionSets.Add(“MyTempSet”)
‘ 2. DXFグループコードによるフィルタリング (ブロック参照のみを狙い撃ち)
filterType(0) = 0
filterData(0) = “INSERT”
sset.Select acSelectionSetAll, , , filterType, filterData
‘ 3. 抽出後の絞り込み (ここが最も効率的)
For Each blkRef In sset
‘ ブロック名が一致するか
If UCase(blkRef.Name) = “MY_BLOCK_NAME” Then
‘ 属性値のチェック
If blkRef.HasAttributes Then
attribs = blkRef.GetAttributes
For i = LBound(attribs) To UBound(attribs)
‘ タグ名「PART_NO」の値が「A-100」のものを抽出
If attribs(i).TagString = “PART_NO” And attribs(i).TextString = “A-100” Then
‘ ここに抽出後の処理を記述 (例: ハイライト)
blkRef.Highlight True
End If
Next i
End If
End If
Next blkRef
‘ 4. 後処理 (メモリリークを防ぐため必ず解放)
sset.Delete
End Sub
3. 実務で勝つための「設計の勘所」
① SelectionSetの「削除」を忘れない
VBAで最も多いメモリリークの原因は、`SelectionSets` を削除せずに終了することだ。AutoCADは一度作成された名前のセットを再利用しようとしてエラーを吐く。必ず `On Error Resume Next` を駆使して、確実にクリアする習慣をつけよ。
② 属性値(Attribute)の罠
`GetAttributes` は配列を返す。この配列は「ブロック定義の属性順」とは限らない。特にブロックを再定義したり、属性を後付けした場合、インデックスがずれることがある。必ず `TagString` をループで比較して目的の属性を特定すること。インデックス直接指定は「地雷」である。
③ データベース連携時のトランザクション意識
もしこの属性値をExcelやSQLに書き出すなら、「1オブジェクトごとにファイルを開閉しない」こと。
- メモリ上に一旦CollectionやDictionaryに格納する。
- 処理の最後にまとめてCSV出力やDB更新を行う。
この「I/Oの最小化」が、数千個のブロックを処理する際の勝負を分ける。
結び:エンジニアとしての矜持
VBAは、正しく書けば最強の自動化ツールだが、無作法に書けば図面を破壊する凶器にもなる。
今回紹介した「SelectionSetによるフィルタリング」と「後処理の確実な解放」は、私の現場では基本中の基本だ。この作法を身につければ、AutoCADの挙動を完全に制御下に置くことができる。さあ、コードを書いて、泥臭い手作業から自分自身を解放しよう。
何か行き詰まったら、いつでも戻ってこい。この「極限の知見」は、君の武器になるはずだ。
