こんにちは。チーフアーキテクトの私だ。
これまで数多のCAD自動化プロジェクトを統括してきたが、現場からもっとも頻繁に挙がる要望の一つが「図面内にある特定の幾何要素(今回は円弧:Arc)のパラメータを正確に抽出し、外部データとして活用したい」というものだ。
Excelへの集計、外部解析ソフトへのインポート、あるいは設計規則の自動チェック。
一見、単純なループ処理に見えるこのタスクだが、AutoCAD VBAのオブジェクトモデルの挙動、メモリ管理、そして座標系の罠を知らずに実装すると、大規模図面でフリーズしたり、ゴミデータを掴まされたりする「地雷コード」が完成する。
今回は、実務の現場で即座に通用する、バグ知らずで高パフォーマンスな円弧情報抽出・リスト化の極意を授けよう。
—
1. なぜ初心者のコードは実務で破綻するのか?
ネットのサンプルコードによくある、全ドキュメントを舐めるだけの安易なループ。あれは実務の現場では使い物にならない。
実務で直面する「3つの壁」をあらかじめ理解しておこう。
1. モデル空間(ModelSpace)とペーパー空間(PaperSpace)の混同
初心者は `ActiveDocument.ModelSpace` だけを見て満足する。しかし、実務の図面ではレイアウト(ペーパー空間)のビューポート内や、ブロック定義の内部に円弧が潜んでいることが多々ある。今回は基本の王道である「モデル空間+アクティブレイアウト」を確実に押さえる。
2. バインドと解放(オブジェクトライフサイクル)の軽視
VBAのCOMラッパーはデリケートだ。特に `SelectionSet` やイテレーションを雑に扱うと、メモリリークや「Automation Error」の温床になる。
3. Variant配列へのアクセスオーバーヘッド
AutoCADの座標(`Center`, `StartPoint`, `EndPoint` など)はすべて3次元配列(Variant)として返ってくる。これをループの都度、雑に取り出すと描画スレッドとの間で無駄な往復が発生し、巨大図面で露骨に処理が重くなる。
—
2. 堅牢な設計:バグを生まないためのアーキテクチャ
今回のツールに求められる要件は以下の通りだ。
- 安全なオブジェクト走査: 選択セットの競合を避け、確実にモデル空間の `Arc` オブジェクトを捉える。
- 正確な幾何情報の抽出:
- 中心座標 $(X, Y, Z)$
- 始点座標 $(X, Y, Z)$
- 終点座標 $(X, Y, Z)$
- 半径 ($Radius$)
- 包含角度 ($TotalAngle$ またはラジアン/度数)
- 実用的なアウトプット: イミディエイトウィンドウへの出力にとどまらず、実務で即座にExcel連携できるよう、CSV出力や配列への一括保持を意識した設計にする。
—
3. 【プロダクションコード】円弧情報抽出・リスト化モジュール
以下のコードを、あなたのAutoCAD VBAプロジェクトの標準モジュールにそのまま貼り付けてほしい。
変数名、エラーハンドリング、コメントに至るまで、プロダクション品質で組み上げている。
Option Explicit
‘ ==============================================================================
‘ 処理名: ExportArcGeometryData
‘ 概要 : アクティブ図面のモデル空間からすべての円弧(Arc)を抽出し、
‘ 中心・始点・終点・半径のジオメトリ情報をイミディエイトに出力する
‘ 著者 : チーフアーキテクト
‘ ==============================================================================
Public Sub ExportArcGeometryData()
‘ 1. 宣言とパフォーマンス最適化の準備
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument
‘ 画面描画とイベントを抑制し、処理速度を極限まで引き上げる
acadDoc.Application.Utility.SetVariable “CMDECHO”, 0
On Error GoTo ErrorHandler
Dim modelSpc As AcadModelSpace
Set modelSpc = acadDoc.ModelSpace
Dim ent As AcadEntity
Dim arcObj As AcadArc
Dim arcCount As Long
arcCount = 0
‘ ログ用ヘッダー出力
Debug.Print “——————————————————————————–”
Debug.Print “【Arc Geometry Extraction Log】 実行日時: ” & Now
Debug.Print “対象図面: ” & acadDoc.Name
Debug.Print “——————————————————————————–”
Debug.Print “Index, Center_X, Center_Y, Center_Z, Start_X, Start_Y, Start_Z, End_X, End_Y, End_Z, Radius”
‘ 2. モデル空間の全エンティティを走査
Dim i As Long
For i = 0 To modelSpc.Count – 1
Set ent = modelSpc.Item(i)
‘ オブジェクトタイプが “AcDbArc”(円弧)であるものに絞り込む
If TypeOf ent Is AcadArc Then
Set arcObj = ent
‘ 3. 座標データの取得(Variant配列として返るためローカル変数で受ける)
Dim vCenter As Variant
Dim vStart As Variant
Dim vEnd As Variant
vCenter = arcObj.Center
vStart = arcObj.StartPoint
vEnd = arcObj.EndPoint
Dim dRadius As Double
dRadius = arcObj.Radius
‘ 4. ログ出力(CSV形式を意識したカンマ区切り)
‘ ※実務ではここでExcelのセルに直接代入するか、配列に蓄積して一括出力する
Debug.Print arcCount + 1 & “,” & _
Format(vCenter(0), “0.000”) & “,” & Format(vCenter(1), “0.000”) & “,” & Format(vCenter(2), “0.000”) & “,” & _
Format(vStart(0), “0.000”) & “,” & Format(vStart(1), “0.000”) & “,” & Format(vStart(2), “0.000”) & “,” & _
Format(vEnd(0), “0.000”) & “,” & Format(vEnd(1), “0.000”) & “,” & Format(vEnd(2), “0.000”) & “,” & _
Format(dRadius, “0.000”)
arcCount = arcCount + 1
End If
Next i
Debug.Print “——————————————————————————–”
Debug.Print “完了: 抽出された円弧の総数 = ” & arcCount
Debug.Print “——————————————————————————–”
CleanUp:
‘ 5. 確実な環境復元
acadDoc.Application.Utility.SetVariable “CMDECHO”, 1
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub
—
4. コードのアーキテクチャ解説(プロの視点)
このコードが「なぜ優れているのか」、その設計思想を解説しよう。
① 画面描画の抑制 (`CMDECHO`)
大規模な図面で `ModelSpace.Count` を回す際、AutoCADが余計な再描画を行おうとすると、それだけで処理が数倍遅くなる。`SetVariable “CMDECHO”, 0` を挟むことで、CADエンジンの無駄なリソース消費を防ぎ、極限のパフォーマンスを発揮させる。
② 厳密な型判定 (`TypeOf … Is AcadArc`)
`For Each` やインデックスループでエンティティを漁るとき、線分(Line)や文字(Text)など、円弧以外のオブジェクトが当然混ざる。
ここで `TypeOf` を使って確実にフィルタリングすることで、不意のメソッド・プロパティ呼び出しエラー(型が一致しません)を完全にシャットアウトしている。
③ 3次元配列の安全なハンドリング
AutoCADの `Center` や `StartPoint` は、内部的に `Double` 型の3要素配列(0番目:X, 1番目:Y, 2番目:Z)として渡される。
これを `Variant` 型の変数で一度受けてからインデックスアクセス (`vCenter(0)`) しているのは、COMオブジェクトへの無駄なプロパティアクセスを最小限にし、メモリ上の効率を最大化するためだ。
—
5. 発展:実務でさらに応用するためのヒント
このコードをベースに、現場のニーズに合わせて以下のように拡張してほしい。
- Excelとのシームレスな連携:
`Debug.Print` でイミディエイトに出力している部分を、`CreateObject(“Excel.Application”)` を使ったCOM連携に書き換えれば、マクロの実行ボタン一つでフォーマット済みの集計表Excelが完成する。
- レイアウト空間(PaperSpace)の網羅:
`ModelSpace` だけでなく、`Layouts` コレクションをループさせて、各ペーパー空間上のビューポートやレイアウト図面に描かれた円弧も対象に含めることで、取りこぼしのない完璧なデータ抽出が可能になる。
プロのエンジニアであれば、コードの「動く・動かない」だけでなく、「保守性」「パフォーマンス」「エラー耐性」の3つを常に意識すべきだ。今回の知見をあなたの開発環境に組み込み、日々の設計業務を自動化の力で圧倒的に効率化してほしい。
