【実務・中級編】【実務中級】AcadDocument.Utility.GetEntityで選択ミスを許容する「リトライ・ループ」の実装:実務で使える堅牢な選択ツール – AutoCAD VBA解析バイブル

スポンサーリンク

序文:なぜあなたのツールは「空振り」で死ぬのか

AutoCAD VBAの実務ツールにおいて、最もユーザーの不満が溜まるポイントはどこか。それは「操作の不備に対する脆弱性」だ。

`AcadDocument.Utility.GetEntity` メソッドは、ユーザーに図形を選択させる極めて基本的な関数だが、標準的な書き方では、ユーザーが図形のない空間をクリックした瞬間にランタイムエラーを吐いて停止する。あるいは、`On Error Resume Next` で強引に黙らせたとしても、その後の処理で `Nothing` を参照して結局クラッシュする。

これは「素人仕事」だ。プロが設計するツールは、ユーザーの「ミス」を「例外」として扱わない。「ミスは必ず起きるもの」として設計に組み込む。

今回は、実務の現場で絶対に避けて通れない、図形選択を「成功するまで、あるいは明確にキャンセルされるまで」繰り返す、堅牢なリトライ・ループの実装を伝授する。

1. 脆弱なコードと堅牢なコードの決定的な差

初心者は、単に `GetEntity` を呼び出す。中級者は `On Error` で囲む。だが、シニアアーキテクトは 「再試行のライフサイクル」 を設計する。

避けるべき「その場しのぎ」の例

‘ 非推奨:エラーが起きたら即終了、あるいは不安定な挙動
Dim ent As AcadEntity
Dim pt As Variant
On Error Resume Next
ThisDrawing.Utility.GetEntity ent, pt, “選択してください”
If ent Is Nothing Then Exit Sub ‘ 何も選ばれなかった時の処理が甘い

このコードでは、空クリック(空振り)と、ESCキーによるキャンセルを区別できない。また、一度失敗した後に再度入力を促す柔軟性もない。

2. 極限の堅牢性を備えたリトライ・ループの実装

実務でそのまま使える、洗練された関数を紹介する。この関数の肝は、「エラー番号の精査」「ユーザーへのフィードバック」だ。

プロダクション・コード:`RobustSelectEntity`

”’

”’ ユーザーが有効な図形を選択するまで入力を促し続ける堅牢な選択関数
”’

”’ 選択されたオブジェクトを格納する変数 ”’ (任意)特定のオブジェクト型のみ許可する(例: “AcDbLine”) ”’ True: 成功, False: ユーザーによるキャンセル(ESC)
Public Function RobustSelectEntity(ByRef selectedObj As AcadEntity, Optional ByVal filterType As String = “”) As Boolean
Dim pickPt As Variant
Dim retryFlag As Boolean

‘ 初期化
Set selectedObj = Nothing
RobustSelectEntity = False

Do
retryFlag = False
Err.Clear
On Error Resume Next

‘ 図形選択の実行
ThisDrawing.Utility.GetEntity selectedObj, pickPt, vbCrLf & “対象の図形を選択してください(キャンセルはESC): ”

‘ エラーハンドリングの要
If Err.Number <> 0 Then
‘ 2147352567 (0x80020009) 等は、空クリックやESC時に発生する
‘ Descriptionを確認し、キャンセルか空振りかを判定
If InStr(Err.Description, “キャンセル”) > 0 Or Err.Number = -2145320851 Then
‘ ユーザーが意図的にESCを押した場合
ThisDrawing.Utility.Prompt vbCrLf & “選択がキャンセルされました。”
Exit Function
Else
‘ 空振り(図形のない場所をクリック)の場合
ThisDrawing.Utility.Prompt vbCrLf & “図形が検出されませんでした。もう一度クリックしてください。”
retryFlag = True
End If
Else
‘ 図形は選択されたが、型チェックが必要な場合
If filterType <> “” Then
If selectedObj.ObjectName <> filterType Then
ThisDrawing.Utility.Prompt vbCrLf & “選択されたのは ” & selectedObj.ObjectName & ” です。 ” & filterType & ” を選択してください。”
Set selectedObj = Nothing
retryFlag = True
End If
End If
End If
On Error GoTo 0

Loop While retryFlag

If Not selectedObj Is Nothing Then RobustSelectEntity = True
End Function

3. アーキテクトが語る実装のポイント

① エラー番号 `-2145320851` の正体

AutoCAD VBAにおいて、`GetEntity` でESCキーが押された際、あるいは空振りの際の挙動は、環境やバージョンによって微妙に異なることがある。そのため、`Err.Number` だけでなく、`Err.Description` を確認するか、あるいは「エラーが出た=図形が取得できなかった」とシンプルに捉えた上で、ループを継続させる設計が最も安全だ。

② `filterType` による型の厳密な管理

実務では「線分だけを処理したい」「ポリラインだけを選ばせたい」というケースが殆どだ。この関数のように `ObjectName`(例: `AcDbLine`, `AcDbPolyline`, `AcDbBlockReference`)を判定基準に組み込むことで、後続の処理でキャストエラー(型不一致)が起きるリスクを根絶できる。

③ ユーザー体験(UX)の向上

空振りした際に何もメッセージを出さないツールは、ユーザーに「フリーズしたのか?」という不安を与える。`ThisDrawing.Utility.Prompt` を使い、コマンドラインに「何が起きたのか(空振りしたのか、型が違うのか)」を明示することは、プロフェッショナルなツールとしての最低限の礼儀である。

4. 外部データベースやファイル連携への応用

このリトライ・ループは、単体で完結するものではない。例えば、選択した図形のハンドル(Handle)をキーにして外部のデータベースやExcelから属性情報を引っ張ってくる場合、以下のようなガードレールを設置せよ。

1. ハンドルの永続性: 図形が選択されたら、即座に `selectedObj.Handle` を取得し、ログに記録する。
2. トランザクションの意識: 選択後の処理が重い(DB書き込み等)場合、リトライ・ループの中で安易にDB接続を開かないこと。選択が完了し、`RobustSelectEntity` が `True` を返してから接続を開始するのが鉄則だ。

結論:コードの堅牢性は、ユーザーへの敬意である

「正しく操作すれば動く」ツールは、まだベータ版だ。
「誤操作しても壊れず、正解へ導いてくれる」ツールこそが、現場で愛され、長く使われる。

今回紹介したリトライ・ループの構造は、`GetPoint` や `GetDistance` など、あらゆる対話型メソッドに応用できる。このロジックをあなたの標準ライブラリ(基盤クラス)に組み込み、二度と「空振りエラー」に怯えることのない開発環境を構築してほしい。

それが、AutoCAD VBAを掌握するということだ。

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