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という巨大なレガシーを、快適な自動化プラットフォームへと変貌させることができる。諸君のコードに幸あれ。
