こんにちは!AutoCADの自動化の世界へようこそ。
マクロの記録ボタンを押して出てくるコードを眺めるだけの日々は、もうおしまい。ここからは、AutoCADの心臓部である「オブジェクトモデル」を自在に操り、プロのエンジニアとしての第一歩を踏み出しましょう。
今回取り組むテーマは、「`AcadDocument.Utility.GetCorner`を用いたラバーバンド付き矩形範囲の取得と、その範囲内の図形集計」です。
「難しそう……」なんて身構える必要はありません。ここをクリアすれば、ユーザーと対話しながら図面をダイナミックに操作する「ワンランク上のVBAツール」が作れるようになります。優しく、そして本質的なところまで丁寧に解説していきますね。
—
1. なぜ「GetCorner」なのか?(基本概念の理解)
AutoCAD VBAでユーザーから入力を受け取る際、`InputBox`のような味気ないダイアログボックスを使っていませんか?
CADの操作は、やっぱり「画面上でクリックして選ぶ」のが直感的で一番スマートです。
ここで登場するのが `AcadUtility` オブジェクトが持つメソッドたちです。
- `GetPoint`:画面上の1点(座標)を取得する
- `GetEntity`:画面上の図形を1つクリックして取得する
- `GetCorner`:1点目を基準として、マウスの動きに合わせて「ラバーバンド(枠線)」を伸縮させながら2点目(矩形の対角点)を取得する
今回は、この `GetCorner` を使って「今、どこからどこまでの範囲を指定したか」を視覚的に捉え、その中にある図形(BOMや部品の集計対象)をごっそりキャッチするツールを作ります。
—
2. 実践!ラバーバンド付き矩形範囲の集計ツール
百聞は一見に如かず。まずは実務でそのまま使えるコード全体像をお見せします。
VBAエディタ(Alt + F11)を開き、標準モジュールに以下のコードを貼り付けてみてください。
Sub CountBlocksInRubberBandRect()
On Error GoTo ErrorHandler
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument
Dim util As AcadUtility
Set util = acadDoc.Utility
‘ 1. ユーザーに1点目(基点)を指定してもらう
Dim basePoint As Variant
basePoint = util.GetPoint(, vbCrLf & “【範囲指定】矩形の1点目をクリックしてください: “)
‘ 2. 1点目を基点として、GetCornerでラバーバンド矩形を描かせる
Dim cornerPoint As Variant
cornerPoint = util.GetCorner(basePoint, vbCrLf & “2点目(対角点)をクリックして範囲を決定: “)
‘ 3. 取得した2点から、最小/最大の座標(バウンディングボックス)を算出する
Dim minPt(0 To 2) As Double
Dim maxPt(0 To 2) As Double
Call CalculateBounds(basePoint, cornerPoint, minPt, maxPt)
‘ 4. 指定範囲内の図形(今回はブロック参照)をスキャンして集計する
Dim blockCounts As Object
Set blockCounts = CreateObject(“Scripting.Dictionary”)
Dim ent As AcadEntity
Dim counter As Long
counter = 0
‘ モデル空間全体をループ(実務ではSelectionSet推奨ですが分かりやすさ重視で全走査)
Dim i As Long
For i = 0 To acadDoc.ModelSpace.Count – 1
Set ent = acadDoc.ModelSpace.Item(i)
‘ ブロック参照(AcadBlockReference)かつ、指定矩形内にあるか判定
If TypeOf ent Is AcadBlockReference Then
If IsInsideRect(ent.InsertionPoint, minPt, maxPt) Then
Dim blkRef As AcadBlockReference
Set blkRef = ent
‘ 辞書オブジェクトで名前ごとにカウントアップ
If blockCounts.Exists(blkRef.Name) Then
blockCounts(blkRef.Name) = blockCounts(blkRef.Name) + 1
Else
blockCounts.Add blkRef.Name, 1
End If
counter = counter + 1
End If
End If
Next i
‘ 5. 結果の出力
Dim resultMsg As String
resultMsg = “— 選択範囲内のブロック集計結果 —” & vbCrLf
Dim key As Variant
For Each key In blockCounts.Keys
resultMsg = resultmsg & key & ” : ” & blockCounts(key) & ” 個” & vbCrLf
Next key
MsgBox resultMsg, vbInformation, “集計完了 (総数: ” & counter & “個)”
Exit Sub
ErrorHandler:
‘ ユーザーがESCキーでキャンセルした場合のエラー番号(-2147352567 または 般エラー)
If Err.Number <> 0 Then
‘ キャンセル時は静かに抜ける
Exit Sub
End If
End Sub
‘ 補助関数:2点から矩形のMin/Max座標を正しく再計算する
Private Sub CalculateBounds(pt1 As Variant, pt2 As Variant, ByRef minPt As Variant, ByRef maxPt As Variant)
Dim j As Integer
For j = 0 To 2
If pt1(j) < pt2(j) Then
minPt(j) = pt1(j)
maxPt(j) = pt2(j)
Else
minPt(j) = pt2(j)
maxPt(j) = pt1(j)
End If
Next j
' 2次元(XY平面)の判定に絞るためZ軸の処理を補正
minPt(2) = 0: maxPt(2) = 0
End Sub
' 補助関数:座標が矩形内に入っているか判定
Private Function IsInsideRect(targetPt As Variant, minPt As Variant, maxPt As Variant) As Boolean
If targetPt(0) >= minPt(0) And targetPt(0) <= maxPt(0) And _
targetPt(1) >= minPt(1) And targetPt(1) <= maxPt(1) Then
IsInsideRect = True
Else
IsInsideRect = False
End If
End Function
---
3. コードのキモと「知っておくべき極意」
このコードには、実務で絶対に知っておくべきAutoCAD VBAの重要なテクニックが詰まっています。いくつかピックアップして解説しますね。
① `GetCorner` は「1点目」が命
`util.GetCorner(basePoint, …)` の第一引数には、「先ほど取得した1点目(basePoint)」を必ず渡します。これがあることで、AutoCADは「この点を起点にして枠を広げよう」と認識し、画面上に美しいラバーバンド(点線の矩形)を描画してくれます。ユーザーは視覚的に範囲を確認しながらクリックできるため、操作ミスが劇的に減ります。
② 座標の大小関係に注意(`CalculateBounds` の理由)
ユーザーがマウスを動かす方向によって、1点目と2点目のX・Y座標の大小関係はバラバラになります(右上に引っ張るか、左下に引っ張るかで変わる)。
そのため、そのまま比較すると「範囲内にあるのに判定漏れする」という恐ろしいバグが起きます。補助関数 `CalculateBounds` を挟み、常に「小さい方をMin、大きい方をMax」に正規化するのがプロの常道です。
③ エラーハンドリング(ESCキー対策)
CADの操作中、ユーザーが「あ、やっぱやめよう」と `ESC` キーを押すことはよくあります。そのとき、VBAが「実行時エラー」で強制終了してはツールとして失格です。
`On Error GoTo ErrorHandler` を仕込み、ユーザーのキャンセル操作を優しく受け流す配慮(防衛的プログラミング)を忘れずに実装しましょう。
—
4. 陥りがちな罠と実務での発展形
今回のコードは分かりやすさを優先してモデル空間を素直にループしていますが、実務の巨大図面(数万オブジェクトがある図面)では少し処理が重くなることがあります。
- もっと高速化したい場合:
全走査(Forループ)ではなく、AcadSelectionSet(選択セット)の `SelectByPolygon` や、AutoCADデータベースの空間インデックスを活用すると、一瞬で対象を絞り込めます。
- ブロック属性(Attribute)も読み込みたい場合:
`AcadBlockReference` の `GetAttributes` メソッドを使えば、図形に埋め込まれた「型番」や「メーカー名」などのテキストデータも同時に取得でき、本格的なBOM(部品表)自動生成システムへと昇華させることができます。
—
まとめ
今回は、`AcadDocument.Utility.GetCorner` を使ったラバーバンド付きの視覚的な範囲指定と、それを用いた図形集計のロジックを解説しました。
「画面から入力を受け取り、計算し、結果を返す」
この一連の流れがスムーズに書けるようになると、AutoCAD VBAでできないことはほとんどなくなります。ぜひご自身の設計業務や図面整理の現場に持ち帰り、カスタマイズしてみてくださいね。
ここをクリアしたあなたなら、もう初級者卒業です!次のステップへ進みましょう。
