【テクニカル・上級編】図面上の特定のオブジェクトを自動選択!AcadDocumentのSelectionSets – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する:SelectionSetsの深淵と、その「死」を制御する技術

AutoCAD VBAにおいて、`SelectionSets`は諸刃の剣だ。
多くの開発者が「なんとなく」使い、そして「なぜか落ちる」「なぜか重くなる」という負の連鎖に陥る。実務レベルで数万のオブジェクトを扱う大規模図面において、安易な実装はシステムを殺す。

今日は、AutoCADという巨大なドキュメントオブジェクトモデル(DOM)の中で、いかにして「狙ったオブジェクト」を高速かつ安全に抽出するか。その極限の知見を授けよう。

1. SelectionSetsの「メモリリーク」を制する

`SelectionSets`を扱う上で最大の過ちは、オブジェクトを明示的に削除せず、`AcadDocument`にゴミを溜め続けることだ。`Add`メソッドで作成したセットは、AutoCADのセッションが終了するまでメモリに残り続ける。

鉄則:生成と破棄の対称性

必ず`Delete`メソッドを呼び出し、オブジェクトを解放せよ。エラーハンドリングを怠れば、再実行時に「既に存在する」というエラーで沈黙することになる。

‘ 伝説的なエンジニアが書くべき、堅牢なSelectionSetsの生成パターン
Public Function GetTargetSelectionSet(ByVal setName As String) As AcadSelectionSet
Dim doc As AcadDocument: Set doc = ThisDrawing
Dim sset As AcadSelectionSet

‘ 既存の同名セットがあれば削除(クリーンアップ)
On Error Resume Next
Set sset = doc.SelectionSets.Item(setName)
If Not sset Is Nothing Then
sset.Delete
End If
On Error GoTo 0

‘ 新規作成
Set sset = doc.SelectionSets.Add(setName)
Set GetTargetSelectionSet = sset
End Function

2. DXFコードによる極限のフィルタリング

全オブジェクトをループで回して `If` 文で条件分岐させるなど、愚の骨頂だ。AutoCAD内部の強力なフィルタリングエンジン(DXFコード)を直接叩け。これはSQLの`WHERE`句に相当する。

例えば、「特定の画層にある、赤色の線分のみ」を抽出するフィルタは、以下のように構成する。

Public Sub SelectByFilter()
Dim sset As AcadSelectionSet
Set sset = GetTargetSelectionSet(“TempSet”)

‘ フィルタ条件の定義
Dim filterType(0 To 2) As Integer
Dim filterData(0 To 2) As Variant

‘ DXFコード 0: オブジェクトタイプ (LINE)
filterType(0) = 0: filterData(0) = “LINE”
‘ DXFコード 8: 画層名
filterType(1) = 8: filterData(1) = “STRUCTURE_LAYER”
‘ DXFコード 62: 色 (赤=1)
filterType(2) = 62: filterData(2) = 1

‘ 高速選択の実行
sset.Select acSelectionSetAll, , , filterType, filterData

‘ ここで処理…
Debug.Print “選択されたオブジェクト数: ” & sset.Count

‘ 用が済んだら即座に抹消
sset.Delete
End Sub

3. パフォーマンスの真髄:Windows APIとの連携

大規模図面で`Select`を実行すると、AutoCADの画面更新(再描画)が走り、処理が著しく遅延することがある。ここで、Windows APIを使用して一時的に描画を凍結するテクニックが有効だ。

`LockWindowUpdate`(もしくは`SendMessage`の`WM_SETREDRAW`)を用いて、バックグラウンドでの選択処理を高速化せよ。

‘ User32.dll を用いた描画抑制の定義
Private Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hwndLock As LongPtr) As Long

Public Sub HighSpeedSelection()
Dim acadHwnd As LongPtr
acadHwnd = ThisDrawing.hwnd

‘ 描画ロック
LockWindowUpdate acadHwnd

‘ … ここに重い処理を記述 …

‘ 描画ロック解除
LockWindowUpdate 0
End Sub

4. チーフアーキテクトからの忠告

1. Late Bindingを過信するな: 開発環境ではEarly Binding(参照設定)を使い、デバッグ時には型チェックを最大限に活用せよ。
2. イベントの監視: `SelectionSets`を操作する際は、AutoCADの`BeginCommand`等のイベントと競合しないよう注意が必要だ。トランザクション管理が甘いと、図面ファイルそのものが破損するリスクがある。
3. レガシーの墓場: 古いAutoCAD(2010以前など)では、`SelectionSet`の挙動が不安定な場合がある。その場合は、`SendCommand`で `_SELECT` コマンドを文字列として送り込む「原始的だが確実な手法」にフォールバックすることも、エンジニアとしての引き出しの一つだ。

結論

SelectionSetsの操作は、単なるコード記述ではない。AutoCADのメモリ空間に対する「外科手術」だ。不要なオブジェクトは即座に切り離し、フィルタリングは可能な限りAutoCADのカーネルに委ねる。

この規律を守れる者だけが、AutoCADという巨大なレガシーを、快適な自動化プラットフォームへと変貌させることができる。諸君のコードに幸あれ。

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