AutoCAD VBAを掌握する極限の知見
【実務中級】AcadDocument.Utility.GetEntityでの「選択対象のフィルタリング」:円やポリライン以外が選ばれた場合に再選択を促す堅牢なUI
開発プロジェクトの現場において、VBAマクロが「おもちゃ」から「実用に耐えうるツール」へと脱却する分岐点がどこにあるか知っているか?
それは、「ユーザーの誤操作をいかに美しく、かつ強靭にいなすか」という例外処理の作り込みに他ならない。
特に、画面上の図形を対話的に取得する `AcadDocument.Utility.GetEntity` メソッドは、現場のツール開発で高頻度で使用されるが、素朴な実装のままでは致命的な脆弱性を抱える。ユーザーが意図した図形(たとえば「軽量ポリライン」や「円」)ではなく、うっかり「寸法線」や「文字(MText)」をクリックした瞬間、マクロは冷酷なランタイムエラーを吐いて強制終了する。あるいは、エラー処理をサボって `On Error Resume Next` で逃げた結果、存在しないオブジェクトへのメソッド呼び出しで無限ループや予期せぬバグを引き起こす。
プロのエンジニアであれば、ここで妥協してはならない。本稿では、CADオペレーターのストレスをゼロにし、堅牢性(ロバストネス)の極みに達した「図形フィルタリング&再選択ループ」の設計思想と実装コードを叩き込む。
—
なぜ愚直な `GetEntity` は実務で使えないのか?
まずは、よくある初心者のアンチパターンを見てみよう。
‘ 【悪例】エラーハンドリングも型チェックもない危険なコード
Sub BadSelectionExample()
Dim acadObj As AcadEntity
Dim basePnt As Variant
‘ ユーザーが図形をクリックするのを待つ
ThisDrawing.Utility.GetEntity acadObj, basePnt, “図形を選択してください: ”
‘ ここでユーザーが線分(Line)以外のものをクリックしていると、
‘ 後続の処理で型ミスマッチやメソッドエラーで即死する
acadObj.Color = acRed
End Sub
このコードの罪は重い。
1. 型の不一致: ユーザーが何を選んだか(Lineなのか、Circleなのか、Textなのか)を検証せずにプロパティにアクセスしている。
2. CAD特有の例外: `GetEntity` 自体、オブジェクトが選択されずにエンターキーなどが押された場合(Error 59 またはユーザーキャンセル)に実行時エラーを発生させる。これをケアしなければマクロは止まる。
実務で求められるのは、「指定した条件の図形が選ばれるまで、優しく、しかし執拗に選択を促し続けるUI」である。
—
堅牢なUI設計:Do-LoopとTypeNameによる厳密な型判定
プロフェッショナルなコードでは、`GetEntity` を `Do…Loop` 構文で囲み、選択されたオブジェクトのクラス名(`TypeName`)を厳密に評価する。さらに、CAD操作につきものの「ユーザーによるESC中断(キャンセル)」をトラップするエラーハンドリングを必ずセットで実装する。
以下に、実務の現場でそのままデプロイ可能なプロダクションコードを提示する。今回は「軽量ポリライン(AcDbPolyline)または円(AcDbCircle)のみを受け付ける」という厳しい条件を例にする。
Option Explicit
Public Sub SelectTargetEntityRobustly()
Dim selectedEntity As AcadEntity
Dim pickPoint As Variant
Dim isValidSelection As Boolean
Dim promptMessage As String
‘ 初回プロンプトの定義
promptMessage = vbCrLf & “【対象指定】円または軽量ポリラインを選択してください: ”
isValidSelection = False
‘ ユーザーが正しい図形を選ぶまで無限ループ(内部で適切に脱出)
Do While Not isValidSelection
‘ エラーハンドリングの有効化(ESCキーによるキャンセル対策)
On Error GoTo ErrorHandler
‘ 1. 図形の取得(GetEntity)
ThisDrawing.Utility.GetEntity selectedEntity, pickPoint, promptMessage
‘ エラー監視を一時停止
On Error GoTo 0
‘ 2. 選択されたオブジェクトの型検証(TypeNameを活用)
If Not selectedEntity Is Nothing Then
Select Case TypeName(selectedEntity)
Case “IAcadLWPolyline”, “IAcadCircle”
‘ 目的のオブジェクトであればフラグをTrueにしてループ抜け
isValidSelection = True
Case Else
‘ 目的外のオブジェクトの場合、警告を出してループ継続
MsgBox “選択された図形は [” & TypeName(selectedEntity) & “] です。” & vbCrLf & _
“円または軽量ポリラインを指定してください。”, vbExclamation, “選択エラー”
‘ プロンプトを少し変えて再試行を促す
promptMessage = vbCrLf & “【再指定】円または軽量ポリラインを選択し直してください: ”
End Select
End If
Loop
‘ — ここから先は保証された安全なオブジェクトに対する処理 —
MsgBox “正常にオブジェクトを取得しました!” & vbCrLf & _
“タイプ: ” & TypeName(selectedEntity) & vbCrLf & _
“ハンドル: ” & selectedEntity.Handle, vbInformation, “処理成功”
‘ 例: 選択された図形の色をシアンに変更する実務処理
selectedEntity.Color = acCyan
selectedEntity.Update
Exit Sub
ErrorHandler:
‘ ユーザーがESCキーを押した場合(Err.Number = -2147352567 または 59等環境による)
If Err.Number <> 0 Then
‘ キャンセル時は静かにプロシージャを抜ける
If MsgBox(“選択がキャンセルされました。処理を中断しますか?”, vbYesNo + vbQuestion, “確認”) = vbYes Then
Exit Sub
Else
‘ 中断しない場合はエラーをクリアしてループを継続
Err.Clear
Resume Next
End If
End If
End Sub
—
チーフアーキテクトが解説する、コードの急所と極意
このコードには、大規模なCAD自動化ツールを支えるための知見が凝縮されている。
1. `TypeName` による厳密なオブジェクト識別
AutoCADのCOMラッパーにおいて、オブジェクトの型判定には `TypeOf … Is` 演算子を使う方法もあるが、VBAの `TypeName` 関数を使う方が、オブジェクトのインターフェース名(`IAcadLWPolyline` や `IAcadCircle` 等)を直接文字列として取得できるため、デバッグ時に「今何が選ばれているのか」がイミディエイトウインドウなどで即座に確認でき、メンテナンス性が圧倒的に高い。
2. ユーザーエクスペリエンス(UX)への配慮
ただ「エラーです」と冷たく突き放すのではなく、「今何を選んでしまったのか(TypeName)」をメッセージボックスで親切に伝えている点に注目してほしい。CADオペレーターは「自分が何をミスしたのか」を視覚的に理解できるため、システムの使いやすさが劇的に向上する。
3. エラーハンドリングのスコープ管理
`On Error GoTo ErrorHandler` は、`GetEntity` という「外部入力(ユーザー依存)」を伴う不安定な処理の直前にのみ適用し、型判定のロジックに入ったら `On Error GoTo 0` で一度エラー監視をリセットしている。これにより、予期せぬバグがエラーハンドラーに誤って吸い込まれるのを防ぎ、デバッグの透明性を確保している。
—
さらに高みを目指すエンジニアへ:SelectionSetとの使い分け
今回は単一の図形を確実に取得するための `GetEntity` に特化して解説したが、実務では「複数選択」や「あらかじめ条件に合うものだけをフィルタリングして一網打尽にしたい」というケースも出てくる。その場合は `AcadSelectionSet.SelectOnScreen` や `Select` メソッドにおけるDXFグループコード(フィルター条件)を活用すべきだ。
しかし、フィルタリングの条件が複雑キメラ的である場合や、「オペレーターに対象を1つずつ確実に確認させながら処理を進めたい」というインタラクティブなUIにおいては、本稿で紹介した `GetEntity` + `TypeName` によるカスタムバリデーションループが最強の武器となる。
小手先のテクニックではなく、オブジェクトのライフサイクルと例外を完全に支配した堅牢なコードこそが、あなたの作る業務自動化ツールを「現場で愛されるインフラ」へと昇華させる。明日からの実装に、この設計思想を必ず取り入れてほしい。
