こんにちは、自動化の深淵へようこそ。私はこれまで数えきれないほどのAutoCADアドインを設計し、現場の「あ、止まった」という溜息を「おぉ、動いた!」という歓喜に変えてきました。
マクロの記録を卒業し、いよいよ自分の手でコードを書き始めたあなた。素晴らしい一歩です。しかし、実務で自作ツールを使い始めると、必ずと言っていいほど直面する「最初の壁」があります。
それは、「ユーザーが図形選択をミスした瞬間に、プログラムがエラーで止まってしまう」という問題です。
今日は、AutoCAD VBAの基礎でありながら、プロの道具にするための必須テクニック「`GetEntity`のリトライ・ループ」について、その真髄を伝授しましょう。ここを乗り越えれば、あなたのツールは「壊れない、信頼される道具」へと進化します。
—
1. なぜ「GetEntity」はすぐに機嫌を損ねるのか?
AutoCAD VBAで図形を一つ選択させる際、最もよく使われるのが `AcadDocument.Utility.GetEntity` メソッドです。
このメソッドは非常に強力ですが、実は非常に繊細(デリケート)です。
- 図形のない「空の空間」をクリックした
- 右クリックやESCキーでキャンセルした
- 図形が重なっていて、うまく掴めなかった
こうした「日常茶飯事の操作ミス」が起きた瞬間、`GetEntity` は即座にランタイムエラーを吐き出し、マクロの実行を強制終了させてしまいます。
「あ、間違えた」でツールが消えてしまう。 これでは現場のプロは使ってくれません。だからこそ、私たちエンジニアが「優しく包み込むようなコード」を書いてあげる必要があるのです。
—
2. 鉄壁の「リトライ・ループ」構造を理解する
エラーを回避し、正しい図形が選ばれるまで何度でも問いかける。この構造を「リトライ・ループ」と呼びます。
ロジックの肝は、以下の3点です。
1. `On Error Resume Next`: エラーが起きてもプログラムを止めない「盾」を構える。
2. `Do…Loop`: 正解に辿り着くまで無限に繰り返す「根性」を持たせる。
3. `Err.Number` のチェック: 失敗した理由を確認し、リセットする。
それでは、実務でそのまま使える「黄金のテンプレート」を見てみましょう。
—
3. 【実践コード】不屈のGetEntity実装
以下のコードは、ユーザーが円(AcadCircle)を正しく選択するまで決して諦めない、堅牢な実装例です。
Sub RobustSelectionTool()
Dim returnObj As AcadObject
Dim basePnt As Variant
Dim isSelected As Boolean
‘ 初期化:まだ選択されていない状態
isSelected = False
‘ プロンプト(指示文)を工夫してユーザーに安心感を与える
On Error Resume Next ‘ ここからエラーの「盾」を有効にする
Do
‘ 1. エラー情報をクリア(前回の失敗を忘れる)
Err.Clear
‘ 2. 図形の選択を試みる
ThisDrawing.Utility.GetEntity returnObj, basePnt, vbCrLf & “円を選択してください(空クリックで再試行 / ESCで終了): ”
‘ 3. エラー判定
If Err.Number <> 0 Then
‘ エラーが発生した場合(空クリックやESC)
‘ もしESCキー等で中断したい場合の処理(任意)
‘ ※実務では無限ループを防ぐため、特定の条件でExit Subさせるのが親切です
If Err.Description Like “キャンセル” Or Err.Number = -2147352567 Then
MsgBox “操作がキャンセルされました。”, vbInformation, “終了”
Exit Sub
End If
‘ 空クリックなどの場合は、メッセージを出してループを続行
ThisDrawing.Utility.Prompt vbCrLf & “【エラー】図形を認識できませんでした。もう一度クリックしてください。”
Else
‘ 4. 図形が選ばれたが、それが「求めている種類」かチェック
If TypeOf returnObj Is AcadCircle Then
‘ 円が選ばれたので、ループを抜ける
isSelected = True
Else
‘ 違う図形(線や文字)だった場合
ThisDrawing.Utility.Prompt vbCrLf & “それは ” & returnObj.ObjectName & ” です。円を選んでください!”
End If
End If
Loop Until isSelected = True
‘ エラーハンドリングを通常に戻す
On Error GoTo 0
‘ — ここから本来の処理 —
returnObj.Highlight True ‘ 選ばれた図形を光らせる(視覚的フィードバック)
MsgBox “素晴らしい!半径 ” & Format(returnObj.Radius, “0.00”) & ” の円が選択されました。”, vbInformation
returnObj.Highlight False
End Sub
—
4. このコードの「ここ」がプロの知恵
① `Err.Clear` の重要性
ループの冒頭で `Err.Clear` を呼んでいますね。これがないと、一度発生したエラー番号が残り続け、2回目以降に正しく選択しても「まだエラー中だ」と誤認してしまいます。「過去を清算してから次に挑む」。これは自動化の鉄則です。
② `TypeOf` による型検定
`GetEntity` は「何かしらの図形」を返しますが、それが「円」なのか「線」なのかまでは指定できません。実務では、円を選んでほしいのに線が選ばれると、その後の処理(例:半径を取得する)で結局エラーになります。
`If TypeOf returnObj Is AcadCircle` と書くことで、「型まで含めた完璧なバリデーション」が可能になります。
③ ユーザーへのフィードバック
`ThisDrawing.Utility.Prompt` を使い、コマンドラインに「なぜ失敗したのか」を表示しています。ユーザーは「なぜマクロが進まないのか」が分からないと不安になります。親切なメッセージは、ツールの品質そのものです。
—
5. 陥りやすいエラー:無限ループの罠
このリトライ・ループを実装する際、一つだけ注意点があります。それは「逃げ道」を作っておくことです。
もしユーザーが「あ、やっぱりこのマクロやめたい」と思ったとき、ESCキーを押してもループが回り続けると、AutoCAD自体を強制終了するしかなくなります。
上記のサンプルコードでは、`Err.Description` を見てキャンセルを検知し、`Exit Sub` する仕組みを入れています。これは、現場で「止まらなくなった!」というクレームを防ぐための、私からのささやかなプレゼントです。
—
結びに:掌握への道
`AcadDocument.Utility.GetEntity` を自在に操れるようになると、ユーザーとの対話型ツールが作れるようになります。それは単なる「自動処理」を超えて、「人間とCADが協調して働く仕組み」への入り口です。
今回の「リトライ・ループ」は、VBAの基礎でありながら、実務レベルのコードには欠かせない極めて重要なパーツです。これが書ければ、あなたのVBAスキルは「初級」を脱し、現場を支える「中級エンジニア」の領域に足を踏み入れたと言っても過言ではありません。
次は、複数の図形を一括で扱う `SelectionSet`(選択セット)の世界があなたを待っています。
一歩ずつ、しかし確実に、AutoCADをあなたの指先に馴染ませていきましょう。応援していますよ!
