こんにちは!AutoCADの自動化の海へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自らの手でCADを自在に操る「エンジニア」の領域へようこそ。先輩エンジニアの私が、今日もしっかりと手を取り合って案内しますね。
実務で図面を描いていると、避けて通れないのが「角度の計算と出力」です。
AutoCADの内部では、角度はすべて「ラジアン(Radian)」という数学的な単位で冷徹に管理されています。しかし、私たちが成果品として出力したり、Excelの計算書にまとたりするときには、「30°15’20″」のような測量単位(度分秒:DMS形式)に直さなければなりません。
「CADの画面上では綺麗な角度が出ているのに、VBAで取得すると『0.5235987…』みたいなワケのわからない小数になってしまう……」
そんな壁にぶつかったことはありませんか?
大丈夫。ここをクリアすれば、AutoCAD VBAのオブジェクトモデルと、実務で使えるデータ変換の極意はバッチリです!一緒にマスターしていきましょう。
—
1. なぜCADの角度は「ラジアン」なのか?そして救世主 `AngleToString` とは
まず知っておいてほしいのは、AutoCADの根底にあるオブジェクトモデルのルールです。
`AcadDocument` オブジェクトのなかで、ユーザーが指定した角度や、線分から算出した角度は、すべてラジアンで返されます。
これを私たちが読める「度(Degree)」、さらには測量で必須の「度・分・秒(DMS)」に変換するには、自前でせっせと「180を掛けてπで割って……」という泥臭い計算をする必要があります。
……が!ここでAutoCAD VBAの強力な武器を思い出してください。そう、`Utility` オブジェクトです。
`AcadDocument.Utility` には、AutoCADが長年培ってきた強力な数学・変換エンジンが詰まっています。その中の一つが、今回主役となる `AngleToString` メソッド です。
`AngleToString` の基本文式
RetVal = AcadDocument.Utility.AngleToString(Angle, Unit, Precision)
ニフティな機能ですが、これを使うと、ラジアン値を「CADの現在の単位設定(UNITSコマンドの状態)」に合わせた文字列に一発で変換してくれます。
しかし、実務の現場では「CADの単位設定に関わらず、強制的に測量単位(度分秒)の文字列として取得し、Excelにきれいに流し込みたい」という強い要望がありますよね。ここからが、プロの腕の見せ所です。
—
2. 実務で直撃する壁:ラジアンから「度・分・秒」への分解ロジック
CADのラジアン値をExcelのセルに「30°15’20″」という形式で書き出すためには、`AngleToString` や自前の数学的アプローチを組み合わせて、ラジアン → 度(Degree) → 度・分・秒への分解を行う必要があります。
ここでは、王道の数学的変換とVBAの文字列操作を組み合わせた、最も堅牢なロジックを伝授します。
匠のVBAコード:測量単位変換&Excelエクスポート
以下のコードを、AutoCADのVBAエディタ(VBE)に貼り付けてみてください。現在の図面から選択した線分の角度を抽出し、裏で起動したExcelへ「度分秒形式」で美しく出力するプログラムです。
Sub ExportAngleToExcel()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.ActiveDocument
Dim entObj As AcadEntity
Dim basePnt As Variant
On Error GoTo ErrorHandler
‘ 1. ユーザーに線分(Line)を選択させる
acadDoc.Utility.GetEntity entObj, basePnt, vbCrLf & “角度を取得する線分を選択してください: ”
‘ 選択されたオブジェクトが線分であるかチェック
If TypeOf entObj Is AcadLine Then
Dim lineObj As AcadLine
Set lineObj = entObj
‘ 2. 始点から終点へのラジアン角を取得
Dim radAngle As Double
radAngle = lineObj.Angle
‘ 3. ラジアンを「度(Degree)」に変換
Dim degAngle As Double
degAngle = radAngle (180 / Atn(1) 4) ‘ 厳密な円周率を使った度数変換
‘ 4. 度・分・秒(DMS)に分解する計算ロジック
Dim d As Long, m As Long, s As Double
Dim dmsStr As String
d = Int(degAngle) ‘ 度
m = Int((degAngle – d) 60) ‘ 分
s = Round(((degAngle – d) 60 – m) 60, 2) ‘ 秒(小数点第2位まで)
‘ 測量単位の文字列に整形(例: 30°15’20″)
dmsStr = d & “°” & m & “‘” & s & “”””
‘ 5. Excelへエクスポートする処理
Call SendToExcel(lineObj.Handle, degAngle, dmsStr)
MsgBox “角度のExcelエクスポートが完了しました!” & vbCrLf & _
“度数: ” & degAngle & vbCrLf & _
“測量単位: ” & dmsStr, vbInformation, “処理成功”
Else
MsgBox “選択されたオブジェクトは線分ではありません。”, vbExclamation, “警告”
End If
Exit_Sub:
Exit Sub
ErrorHandler:
If Err.Number <> -2147352567 Then ‘ ユーザーがESCキーでキャンセルした場合はエラーにしない
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End If
Resume Exit_Sub
End Sub
‘ —————————————————————–
‘ 内部関数: Excelを操作してデータを書き出すプロシージャ
‘ —————————————————————–
Private Sub SendToExcel(entHandle As String, dVal As Double, dmsVal As String)
Dim xlApp As Object
Dim xlWb As Object
Dim xlWs As Object
‘ Excelのインスタンスを生成(起動していなければ新規起動、していれば取得)
On Error Resume Next
Set xlApp = GetObject(, “Excel.Application”)
If xlApp Is Nothing Then
Set xlApp = CreateObject(“Excel.Application”)
End If
On Error GoTo 0
‘ 可視化して作業させる
xlApp.Visible = True
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Sheets(1)
‘ ヘッダーの設定
xlWs.Cells(1, 1).Value = “オブジェクトハンドル”
xlWs.Cells(1, 2).Value = “ラジアン変換(度)”
xlWs.Cells(1, 3).Value = “測量単位(度分秒)”
‘ データの書き込み
xlWs.Cells(2, 1).Value = entHandle
xlWs.Cells(2, 2).Value = dVal
xlWs.Cells(2, 3).Value = dmsVal
‘ 列幅の自動調整
xlWs.Columns(“A:C”).AutoFit
End Sub
—
3. ここでハマる!実務で陥りやすい罠と回避の極意
このコードを組むにあたって、プログラミング初学者やマクロ記録脱却組が必ずと言っていいほどハマる「3つの罠」があります。ここを知っておくだけで、現場でのトラブルシューティング能力が圧倒的に跳ね上がります。
罠その1:円周率の精度不足で「秒」がズレる
VBAには標準で `PI` という定数がありません。よくネットで見かける `3.141592` などとベタ打ちすると、大規模な測量図面や微小な角度を扱う際に、秒単位で誤差(ジッター)が生じます。
> 【解決策】
> コード内にある `Atn(1) 4` は、アークタンジェントを使って数学的に精確な円周率を導き出すVBAの常套手段です。これを使うことで、精度の高い計算が担保されます。
罠その2:浮動小数点の丸め誤差(例:59.9999秒問題)
計算の過程で、本来「60秒」になるはずの値が `59.999999秒` や `60.0001秒` になり、文字列結合したときに見た目が汚くなる現象です。
> 【解決策】
> `Round` 関数を適切に挟むこと、そして「分」が60を超えた場合の繰り上げ処理(厳密な実務ツールを作るなら、秒が60になったら分に+1し、分が60になったら度に+1するキャリー処理)を組み込むと、さらにプロフェッショナルなコードになります。今回はシンプルにするために `Round` で丸めています。
罠その3:Excel連携時の「オブジェクトの解放忘れ」と「多重起動」
`CreateObject` を使ってExcelを操作する際、コードの書き方が悪いと、裏でゾンビプロセス(見えないExcelプロセス)が何個も残り、メモリを食いつぶす原因になります。
> 【解決策】
> 可能な限り `GetObject` で既存のインスタンスをキャッチし、今回はデモンストレーションとして `Visible = True` にしてユーザーに明け渡していますが、完全にバックグラウンドで処理を完結させる場合は、最後に `Set xlApp = Nothing` で綺麗に参照を切るライフサイクル管理を意識しましょう。
—
4. まとめ:基本をクリアすれば、自動化はもっと楽しくなる!
お疲れ様でした!
今回は、`AcadDocument.Utility` の基礎、ラジアンの数学的変換、そしてExcelへのデータエクスポートという、実務で直結するスキルを凝縮してお伝えしました。
- CAD内部のデータ構造(ラジアン)を理解したこと
- `GetEntity` でユーザーの選択を安全に受け取る作法を覚えたこと
- Excelとの連携(Late Binding:レイトバインディング)の基本を押さえたこと
ここをしっかりとクリアできたあなたなら、もう「単なるマクロ記録の使用者」ではありません立派なAutoCAD VBAエンジニアです。
このロジックをベースに、複数図面の一括処理や、座標値(X, Y)の抽出と組み合わせれば、数時間かかる測量計算書の作成を一瞬で終わらせる最強のツールが作れます。ぜひ、あなたの手元の図面で試してみてくださいね。
それでは、次の自動化の海でお会いしましょう。ハッピー・コーディング!
