こんにちは、開発プロジェクトのリーダーの私だ。
AutoCAD VBAの実務において、図面上のデータを機械的に処理するだけのコードはもう卒業してほしい。現場が本当に求めているのは、CAD上の「見た目の数値」と、現実世界の「実寸値」のギャップを埋める、ロバストで実用的な自動化ツールだ。
今回は、中級者へのステップアップとして、`AcadDocument.Utility.GetDistance` をただの「2点間距離の計測」として使うのではなく、「図面の尺度(スケール)」を動的に考慮し、現実世界の構造物寸法(実寸)を瞬時に算出・出力する計算ツールの設計手法を伝授する。
単なるコードのコピペではない。実務で必ず直面する「落とし穴」を回避するための堅牢な設計思想を叩き込む。
—
なぜ、単純な `GetDistance` では実務で使えないのか?
初心者が書くコードはこうだ。
‘ 【悪例】単に座標間のCAD上の単位を返すだけ
Dim dist As Double
dist = ThisDrawing.Utility.GetDistance
MsgBox “距離は ” & dist & ” です”
これの何が問題か?
CADの世界では、1.0 = 1mm(あるいは1インチ)という「作図単位」で描かれている。しかし、A1やA3といった図面枠に収めるため、図面は必ず「1:50」や「1:100」といった尺度(縮尺)を持って縮小・拡大されて作図されている。
つまり、`GetDistance` が返すのは「画面上のCAD空間の生データ(ModelSpace上の数値)」に過ぎない。これをそのまま構造物の実寸として積算やログ出力に使えば、現場は大混乱に陥る。
我々エンジニアが作るべきツールは、「現在のビューポートまたは図面全体の尺度係数を自動的(あるいは対話的)に加味し、実寸のミリメートルやメートルへ換算する」という一工夫が組み込まれた、プロフェッショナルなツールだ。
—
堅牢な設計:実装のポイント
実務で耐えうるツールにするため、以下の3点をアーキテクチャに組み込む。
1. エラーハンドリングとESCキーの捕捉
ユーザーが `GetDistance` の最中に右クリックやESCでキャンセルした際、VBAが無慈悲な実行時エラー(エラー番号: 423等)で停止するのを防ぐ。
2. 図面単位(Units)と尺度の分離
図面のベース単位(ミリメートル、メートルなど)を `LUNITS` や `INSUNITS` から読み取りつつ、ユーザーが指定した「尺度(例: 1/100なら 100)」を乗算する。
3. 拡張性(ログ出力・クリップボード連携)
単に `MsgBox` で見せて終わりではなく、計算結果を即座に利用できるよう配慮する。
—
プロダクションコード:実寸算出計測ツール
以下のコードを、AutoCADのVBAエディタ(`Alt + F11`)の標準モジュールに貼り付けてほしい。実務の現場ですぐに投入できるプロダクションクオリティだ。
Option Explicit
‘ ==============================================================================
‘ 処理名: 尺度考慮型 実寸計測ツール (GetDistance Extended)
‘ 概要 : 2点間のCAD上の距離に、指定された図面縮尺を乗算し、実寸を算出する
‘ 作者 : シニアCAD自動化アーキテクト
‘ ==============================================================================
Public Sub MeasureRealDistanceWithScale()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
Set acadApp = ThisDrawing.Application
Set acadDoc = ThisDrawing.ActiveDocument
On Error GoTo ErrorHandler
‘ 1. ユーザーから「図面尺度」を入力させる(デフォルトは 1:100 なら 100)
Dim scaleFactor As Double
Dim scaleInput As String
scaleInput = InputBox( _
“図面の分母となる尺度を入力してください。” & vbCrLf & _
“(例: 1/50 の場合は ’50’、1/100 の場合は ‘100’)”, _
“実寸計測ツール – 尺度設定”, “100”)
‘ キャンセルまたは空欄の場合は処理を安全に終了
If scaleInput = “” Or Not IsNumeric(scaleInput) Then
MsgBox “処理がキャンセルされました。”, vbInformation, “終了”
Exit Sub
End If
scaleFactor = CDbl(scaleInput)
if scaleFactor <= 0 then
Err.Raise vbObjectError + 1, "MeasureRealDistance", "尺度には正の数値を入力してください。"
End If
' 2. 図面上の2点を取得 (GetDistance)
' ユーザーインタフェース操作のため、画面描画やコマンドプロンプトの制御を意識
Dim cadDistance As Double
Dim promptMsg As String
promptMsg = vbCrLf & "【尺度 1:" & scaleFactor & "】 計測する1点目を指定してください: "
' Utility.GetDistance は、プロンプトと2点目を引数にとることができる
cadDistance = acadDoc.Utility.GetDistance(, promptMsg)
' 3. 実寸の計算(CAD上の距離 × 尺度分母)
' ※必要に応じて、図面の基本単位(mm等)から m への変換などもここで実施
Dim realDistMM As Double
Dim realDistM As Double
realDistMM = cadDistance scaleFactor
realDistM = realDistMM / 1000# ' ミリメートルからメートルへ換算
' 4. 結果の出力(メッセージボックス & コマンドライン出力)
Dim resultMessage As String
resultMessage = "--- 実寸計測結果 ---" & vbCrLf & _
"・CAD上の計測値: " & Format(cadDistance, "#,
0.00″) & ” 単位” & vbCrLf & _
“・適用尺度: 1 / ” & scaleFactor & vbCrLf & _
“————————” & vbCrLf & _
“・実寸 (ミリメートル): ” & Format(realDistMM, “#,
0.00″) & ” mm” & vbCrLf & _
“・実寸 (メートル) : ” & Format(realDistM, “#,
0.03″) & ” m”
‘ 開発者ログとしてコマンドラインにも投げておく(履歴が残るため実務で重宝する)
acadDoc.Utility.Prompt vbCrLf & resultMessage & vbCrLf
‘ ユーザーへの最終通知
MsgBox resultMessage, vbInformation, “計測完了”
Exit Sub
ErrorHandler:
‘ ユーザーがESCキーを押した場合のエラー(Err.Number = -2147352567 などを想定)
‘ もしくは一般的なキャンセル操作
If Err.Number <> 0 Then
If Err.Number = -2147467259 Or InStr(Err.Description, “User”) > 0 Or Err.Number = 423 Then
‘ ユーザーキャンセル時は静かに抜ける
Exit Sub
Else
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error No: ” & Err.Number & vbCrLf & _
“Description: ” & Err.Description, vbCritical, “エラー”
End If
End If
End Sub
—
プロジェクトを成功させるための実務的アドバイス
1. `On Error GoTo` の重要性
CADの対話型メソッド(`GetDistance`, `GetPoint` など)実行中にユーザーが `ESC` を押すと、VBAは容赦なく実行時エラーを吐く。これをハンドリングしないツールは、現場のエンジニアから「使い物にならないゴミ」と判断される。上記の通り、キャンセル時のトラップを必ず実装すること。
2. 単位系のハードコーディングを避ける
今回は分かりやすく「mmからmへの換算(1000で割る)」を固定で入れているが、もし海外案件やインペリアル(インチ・フィート)混交の図面を扱う場合は、`acadDoc.GetVariable(“INSUNITS”)` の値を参照して動的に換算係数を変えるロジックへ拡張してほしい。これができれば君のコードはシニアの領域だ。
3. データベースやExcel連携への布石
このツールで得た `realDistM` などの変数を、そのまま外部のExcelシート(BOMや数量調書)へ `ActiveSheet.Cells(…)` 経由で書き出すようにモジュールを拡張すれば、工数を数十分の一に圧縮するキラーツールに変貌する。
安易な自動化に溺れるな。CADの内部仕様(オブジェクトモデルと座標系)を完全に支配した上で、実務の泥臭い要件をコードに落とし込む――これこそがプロのエンジニアの仕事だ。
次のモジュール開発でも、圧倒的な品質を見せつけてやってくれ。
