AutoCAD VBAの「選択セット重複エラー」を根絶する——プロが現場で使う唯一の解法
AutoCAD VBAを触り始めたエンジニアが、ほぼ100%の確率でぶつかる壁がある。
‘ 誰もが一度は通る「お祈りコード」
Set sset = ThisDrawing.SelectionSets.Add(“MySet”)
‘ → 実行時エラー 457: このキーは既にコレクションに存在します
なぜエラーになるのか? 理由はシンプルだ。AutoCADの`SelectionSets`は、一度作成すると明示的に削除(Delete)しない限り、メモリ上に永続的に残り続けるからだ。
「エラーが出たら無視する」というOn Error Resume Nextによる姑息な回避策は、メモリリークを招き、大規模な図面を開くたびにCADの挙動を不安定にする。本稿では、この悪習を断ち切り、プロダクション環境で胸を張って使える「安全な初期化テンプレート」を伝授する。
—
1. なぜ「その場しのぎ」が致命的なのか
多くのチュートリアルでは、エラーを無視して続行するコードが紹介されている。しかし、それは「選択セットというオブジェクトがメモリ上でゾンビ化している」状態を放置していることに他ならない。
大規模な図面処理や、外部DBと連携した自動化ツールを作成する際、この「ゾンビオブジェクト」が積み重なると、AutoCADのパフォーマンスは確実に劣化する。「使う前に、同じ名前のものが居たら消す」。 これが、アーキテクトとして守るべき、たった一つの鉄則だ。
—
2. 実務で採用すべき「堅牢な初期化関数」
以下のコードは、私のプロジェクトで標準採用している「再利用可能な初期化関数」だ。コピペして標準モジュールに配置してほしい。
”’
”’ 既存のセットが存在すれば削除し、クリーンな状態で返す
”’
”’ 作成する選択セットの名前
”’
Public Function GetSafeSelectionSet(ByVal setName As String) As AcadSelectionSet
Dim sset As AcadSelectionSet
‘ 1. 既存のセットを検索し、存在すれば削除する
On Error Resume Next
Set sset = ThisDrawing.SelectionSets.Item(setName)
If Not sset Is Nothing Then
sset.Delete
Set sset = Nothing
End If
On Error GoTo 0
‘ 2. 新規にセットを作成して返す
Set GetSafeSelectionSet = ThisDrawing.SelectionSets.Add(setName)
End Function
このコードの「設計思想」
- On Error Resume Nextの局所化: 削除プロセスのみに限定し、関数全体を汚さない。
- オブジェクトの即時開放: `Set sset = Nothing`を明記することで、参照カウントを確実にリセットする。
- 戻り値の保証: 常に「まっさらな状態」のオブジェクトが返されるため、呼び出し元ではエラー処理を気にする必要がない。
—
3. 現場で使うための実践的な呼び出し方
ツールを実装する際は、以下のように呼び出す。これで、デバッグ中も、本番環境でも、二度と「名前重複エラー」に悩まされることはない。
Sub ProcessDrawingElements()
Dim mySSet As AcadSelectionSet
‘ 常にクリーンな状態で取得
Set mySSet = GetSafeSelectionSet(“TargetEntities”)
‘ ユーザーに選択を促す、あるいはフィルタで抽出する
mySSet.SelectOnScreen
‘ — ここに業務ロジックを記述 —
‘ 最後にメモリを開放する(プロの嗜み)
mySSet.Delete
End Sub
—
4. アーキテクトからの助言:なぜ保守性が高いのか
この設計の肝は、「状態(State)をシステムに依存させず、コードで制御しきっている点」にある。
もしあなたが、図面を開いたまま長時間にわたるバッチ処理や、外部データベースとの同期ツールを開発しようとしているなら、この「終了時の `Delete`」と「開始時の初期化」を徹底するだけで、アプリのクラッシュ率は劇的に下がる。
AutoCAD VBAは古い言語だが、そのオブジェクトモデルは極めて誠実だ。あなたがリソースのライフサイクルを正しく管理すれば、それに応えて安定した挙動を返してくれる。
まずはこのテンプレートをあなたのツールボックスに組み込み、エラー処理の泥沼から脱出してほしい。次なるステップは、`AcadSelectionSet.Select` におけるフィルタ機能の最適化だ。それについては、また別の機会に深く掘り下げよう。
