こんにちは!AutoCAD VBAの世界へようこそ。
マクロの記録ボタンを押すだけのステップから抜け出し、「いざ本格的な自動化ツールを作ろう!」と意気込んだ矢先、多くの開発者が最初に直面する巨大な壁があります。
それが、今回取り上げる「選択セット(SelectionSet)の重複エラー」です。
図面を描いていると、オブジェクトをまとめて選択して処理したい場面が多々ありますよね。VBAでも「よし、選択セットを作って処理するぞ!」とコードを書いたはずが、2回目実行した瞬間に無情にも「既に存在します(Runtime Error)」というエラーで強制終了させられる……。実務でAutoCAD VBAを扱うなら、誰もが100回は通る通過点です。
今回は、この厄介なエラーを完全に封じ込め、あなたのコードをプロの品質へ引き上げる「Try-Get-Createパターン」の汎用関数の作り方を、優しく徹底的に解説していきますね。ここをクリアすれば、AutoCAD VBAの基礎とオブジェクトモデルの扱い方はバッチリです!
—
1. なぜ「既に存在します」エラーが起きるのか?(根本原因の理解)
まずは、AutoCADのメモリ(オブジェクトモデル)がどうなっているのかを覗いてみましょう。
AutoCAD VBAの頂点には `ThisDrawing`(現在の `AcadDocument`)がいます。その配下にある `SelectionSets` コレクションは、いわば「名前付きの選択グループを管理するロッカー」のようなものです。
[AcadDocument (ThisDrawing)]
└─ [SelectionSets コレクション (ロッカー)]
├─ “MySet1” (すでに存在する!) ── ★ここで Add しようとするとエラー!
├─ “MySet2”
└─ “MySet3”
あなたが `SelectionSets.Add(“MySet1”)` というコードを実行したとき、AutoCADはこう考えます。
> 「おっ、『MySet1』という名前の選択セットを作るんだな。……あれ? ロッカーを覗いたら、さっき作った『MySet1』がまだ残ってるぞ!? 上書きしちゃっていいのか分からないから、とりあえずエラーで止めておこう!」
そう、AutoCAD VBAの選択セットは、一度プログラムで作ると、明示的に削除(Delete)しない限り、図面ファイル(ドキュメント)が開いている間ずっと残り続けるという性質(ライフサイクル)を持っているのです。これが原因の正体です。
—
2. 初学者が陥りがちな「残念な回避策」とプロの視点
このエラーに直面したとき、初学者は次のようなコードを書きがちです。
‘ 【残念な例】エラーを無理やり無視するスタイル
On Error Resume Next
Dim sset As AcadSelectionSet
Set sset = ThisDrawing.SelectionSets.Add(“MySet1”)
On Error GoTo 0 ‘ エラー処理を戻す
「エラーが起きたら無視すればいいや」という発想ですね。動くには動きますが、チーフアーキテクトの視点から言わせると、これは実務では絶対にやってはいけないアンチパターンです。
なぜなら:
1. 既に存在していた「古い選択セット(ゴミデータ)」の中に、過去に詰め込まれたオブジェクトが残ったままになる。
2. その結果、意図しないオブジェクトまで処理対象に巻き込んでしまい、図面を破壊するバグの温床になる。
私たちが目指すべきは、「古いものはキレイに掃除し、新鮮な状態で新しく作り直す」というスマートなアプローチです。
—
3. 解決策:【Try-Get-Createパターン】の汎用関数
それでは、実務で100%の信頼性を発揮する「選択セットを安全に取得・作成する汎用関数」を公開します。
以下のコードを、あなたのVBAプロジェクトの標準モジュール(例: `Module1` など)にそのまま貼り付けてください。
Option Explicit
” ===================================================================
” 汎用関数: 選択セットを安全に取得・新規作成する(Try-Get-Createパターン)
” 引数 setName : 作成・取得したい選択セットの名前
” 戻り値 : 有効な AcadSelectionSet オブジェクト
” ===================================================================
Public Function GetOrCreateSelectionSet(ByVal setName As String) As AcadSelectionSet
Dim targetSSet As AcadSelectionSet
‘ 1. すでに同名の選択セットがメモリ上に存在するかチェック
On Error Resume Next
Set targetSSet = ThisDrawing.SelectionSets.Item(setName)
On Error GoTo 0
‘ 2. 存在する場合は、一度「削除(Delete)」してリセットする
‘ ※重要:選択セット自体を消すだけで、図面上の線や文字などの図形は消えませんご安心を!
If Not targetSSet Is Nothing Then
targetSSet.Delete
End If
‘ 3. 真新しい状態で新しく選択セットを作成し、呼び出し元に返す
Set targetSSet = ThisDrawing.SelectionSets.Add(setName)
Set GetOrCreateSelectionSet = targetSSet
End Function
このコードの何がスゴいのか?
- 存在チェックと消去の自動化: 指定した名前のセットがすでにあれば `Item` で掴み、即座に `Delete` で消去します。これにより、完全にクリーンな状態が保証されます。
- メモリリークとゴミの防止: 毎回作り直すため、古いオブジェクトの残骸がプログラムの邪魔をすることが一切なくなります。
- 戻り値の確実性: 最終的に必ず新しく作成された `AcadSelectionSet` が返されるため、呼び出し元で「空振り(Nothing)」を気にする必要がなくなります。
—
4. 実戦投入!この汎用関数の使い方
先ほど作った汎用関数を使って、実際に図面内の文字(Text)を全選択して処理するマクロの例を見てみましょう。
Sub Sample_SelectTexts()
Dim sset As AcadSelectionSet
Dim filterType(0) As Integer
Dim filterData(0) As Variant
‘ ★ここで神関数を呼び出す!名前が重複していようがエラーは一切起きません。
Set sset = GetOrCreateSelectionSet(“MyWorkingSet”)
‘ フィルターを設定(「TEXT」という文字オブジェクトだけを狙い撃ち)
filterType(0) = 0
filterData(0) = “TEXT”
‘ 図面全体から条件に合うものを選択セットに追加
sset.Select acSelectionSetAll, , , filterType, filterData
‘ 選択できた個数をメッセージで表示
MsgBox “図面内に文字オブジェクトが ” & sset.Count & ” 個見つかりました。”, vbInformation
‘ 【プロの作法】使い終わった選択セットは、メモリ解放のために明示的に消去する
sset.Delete
End Sub
このコードを何度連続で実行しても、あの憎き「既に存在します」エラーは二度と発生しません。ストレスフリーな開発環境の出来上がりです!
—
まとめ:基礎の積み重ねが、強靭なマクロを作る
今回は、AutoCAD VBAのオブジェクトモデルにおける最大のトラップの一つである「選択セットの重複エラー」を、汎用関数によってエレガントに解決する方法を解説しました。
- 選択セットは作ったらメモリに残る性質がある
- エラーを `On Error Resume Next` で逃げるのは悪手(ゴミが残る)
- 「存在確認 ➔ 削除 ➔ 新規作成」のフローを関数化するのがプロの常道
ここをクリアできたあなたなら、もうマクロの記録の卒業生ではありません立派なAutoCAD VBAエンジニアです。この「Try-Get-Create」の思想は、レイヤー管理やブロック定義の操作など、他のオブジェクトを扱う際にもそのまま応用できます。
日々の業務を自動化する相棒として、ぜひこの汎用関数をあなたのVBAライブラリに組み込んでみてください。それでは、快適なAutoCADライフを!
