【実務・中級編】【実務中級】AcadDocument.Utility.AngleToStringで取得した角度を、測量単位(度分秒)形式でExcelへエクスポートする変換ロジック – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:測量角の呪縛を断つ!ラジアンから「度分秒」への完全変換ロジック

開発プロジェクトの現場において、図面上の幾何データを抽出し、Excelの測量計算書や成果品フォーマットへ自動流し込みする要件は枚挙に暇がない。
しかし、ここで多くの開発者が最初の壁にぶつかる。「AutoCAD内部の角度はすべて『ラジアン』であり、実務で求められるのは『30°15’20″』といった測量単位(DMS:度・分・秒)である」という厳然たる事実だ。

ネット上の散逸した情報を見て、「自前で泥臭くラジアンを度に換算し、さらに度から分秒へ分解する剰余演算(Mod)のコード」を書いていないか? 浮動小数点演算の誤差に悩まされ、特定の境界値で「59秒」が「60秒」にならずに切り捨てられるバグに頭を抱えていないか?

世界最高峰の自動化エンジニアである私から言わせれば、それは車輪の再発明であり、AutoCADの強大なAPIをドブに捨てる愚行だ。
AutoCADには、OSや図面設定の角度単位(UNITS)を完全シミュレートして文字列化する、極めて強力なメソッドが存在する。それが `AcadDocument.Utility.AngleToString` だ。

今回は、このネイティブ機能とExcelの強力なCOM連携を組み合わせ、「実務で1ミリの狂いも許されない測量データ自動化エージェント」を構築するための極限の知見を授けよう。

1. なぜ「自前計算」は破綻するのか?設計思想の盲点

初心者は次のようなコードを書きがちだ。

‘ 【アンチパターン】絶対に真似してはいけない泥臭い変換
Dim rad As Double, deg As Double
Dim d As Long, m As Long, s As Double
rad = 1.2345
deg = rad (180 / 314159265358979# 10000000000000#) ‘ 精度不足の温床
‘ ここから泥臭い割り算とModの嵐…

このアプローチがなぜ非実務的なのか、理由は3つある。
1. 浮動小数点の呪い: IEEE 754倍精度浮動小数点数の宿命として、微小な誤差(例: `0.9999999999`秒)が発生し、四捨五入のロジックが崩壊する。
2. 図面環境(UNITS)への不適合: 測量図面では「北基準・時計回り(North-Azimuth)」や「小数点以下の桁数」「方向(度なのかグラドなのか)」が図面ごとに異なる。自前計算はこれらを一切無視するため、図面間の整合性が消え失びる。
3. 保守性の欠如: コードが冗長になり、後任のエンジニアがデバッグ不能に陥る。

解決策:`AngleToString` の完全掌握

AutoCADの `Utility` オブジェクトが持つ `AngleToString` メソッドは、指定したラジアン値を、AutoCADの単位系(`acDegree`, `acDMS` など)に従って、一撃でフォーマット済み文字列に変換してくれる。
これを使わない手はない。

2. プロダクションコード:測量角エクスポート・エンジン

以下のコードは、現在アクティブな図面からすべての線分(Line)の傾きを抽出し、DMS(度分秒)形式に変換した上で、Excelワークシートへ美しくスタイリングして出力する、実務投入可能な完全版モジュールである。

エラーハンドリング、オブジェクトのライフサイクル管理、ExcelのCOMインスタンスのクリーンアップまで、プロの作法をすべて網羅している。

Option Explicit

‘ =========================================================================
‘ モジュール名: modSurveyAngleExporter
‘ 概要 : AutoCAD図面の線分角度をラジアンから度分秒(DMS)に変換しExcelへ出力
‘ 依存関係 : Microsoft Excel XX.X Object Library (事前バインディング推奨)
‘ =========================================================================
Public Sub ExportSurveyAnglesToExcel()
‘ 1. 宣言と環境構築
Dim acDoc As AcadDocument
Set acDoc = ThisDrawing.Application.ActiveDocument

Dim xlApp As Object
Dim xlWb As Object
Dim xlWs As Object
Dim rowIdx As Long

‘ エラーハンドリングの要
On Error GoTo ErrorHandler

‘ 2. Excelアプリケーションの起動 (COMの適切な制御)
Set xlApp = CreateObject(“Excel.Application”)
xlApp.Visible = True
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Sheets(1)
xlWs.Name = “測量角成果一覧”

‘ 3. Excelヘッダーの構築
With xlWs
.Cells(1, 1).Value = “要素ハンドル”
.Cells(1, 2).Value = “始点 X”
.Cells(1, 3).Value = “始点 Y”
.Cells(1, 4).Value = “ラジアン値”
.Cells(1, 5).Value = “測量単位 (DMS)”

‘ ヘッダーのスタイリング(プロの仕事は見た目にも宿る)
With .Range(“A1:E1”)
.Interior.Color = RGB(41, 128, 185)
.Font.Color = RGB(255, 255, 255)
.Font.Bold = True
End With
End With

rowIdx = 2 ‘ データ書き込み開始行

‘ 4. 図面内のモデル空間スキャン
Dim ent As AcadEntity
Dim lineEnt As AcadLine
Dim angleRad As Double
Dim angleDMS As String

Dim sset As AcadSelectionSet
Set sset = CreateSelectionSetSafely(acDoc, “SurveyAngleSS”)

‘ フィルター設定等の拡張性を考慮し、モデル空間の全Lineを走査
Dim i As Long
For i = 0 To acDoc.ModelSpace.Count – 1
Set ent = acDoc.ModelSpace.Item(i)

‘ Lineオブジェクトのみを対象とする
If TypeOf ent Is AcadLine Then
Set lineEnt = ent
angleRad = lineEnt.Angle

‘ 【核心】AngleToStringによる度分秒変換
‘ 引数1: ラジアン値
‘ 引数2: 単位形式 (acDMS = 度分秒)
‘ 引数3: 精度 (4 = 秒未満の小数点以下桁数、環境依存を避けるため明示)
angleDMS = acDoc.Utility.AngleToString(angleRad, acDMS, 4)

‘ Excelへ転記
xlWs.Cells(rowIdx, 1).Value = lineEnt.Handle
xlWs.Cells(rowIdx, 2).Value = lineEnt.StartPoint(0)
xlWs.Cells(rowIdx, 3).Value = lineEnt.StartPoint(1)
xlWs.Cells(rowIdx, 4).Value = angleRad

‘ 文字列として書き込むことでExcel側での勝手な日付変換を防ぐ
With xlWs.Cells(rowIdx, 5)
.Value = “‘” & angleDMS
.HorizontalAlignment = -4108 ‘ センタリング (xlCenter)
End With

rowIdx = rowIdx + 1
End If
Nf:
Next i

‘ 5. 仕上げ(列幅自動調整)
xlWs.Columns(“A:E”).AutoFit

MsgBox “測量角のエクスポートが正常に完了しました。”, vbInformation, “自動化タスク完了”

CleanUp:
‘ 6. オブジェクトのライフサイクル管理(メモリリークの根絶)
On Error Resume Next
If Not sset Is Nothing Then
acDoc.SelectionSets.Item(sset.Name).Delete
End If
Set xlWs = Nothing
Set xlWb = Nothing
Set xlApp = Nothing
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub

‘ ————————————————————————-
‘ 堅牢な選択セット生成ヘルパー(既存名との衝突を防ぐ)
‘ ————————————————————————-
Private Function CreateSelectionSetSafely(doc As AcadDocument, ssName As String) As AcadSelectionSet
Dim ss As AcadSelectionSet
On Error Resume Next
Set ss = doc.SelectionSets.Item(ssName)
If Not ss Is Nothing Then
doc.SelectionSets.Item(ssName).Delete
End If
On Error GoTo 0
Set CreateSelectionSetSafely = doc.SelectionSets.Add(ssName)
End Function

3. チーフアーキテクトが教える「現場でハマる罠」と回避策

上記のコードをそのまま動かすだけでも十分に実用に耐えうるが、さらに大規模なインフラ図面や複雑な実務データに適用する際、以下のポイントを抑えておかないと手痛いしっぺ返しを喰らう。

① Excelの「文字列先頭のシングルクォート(’)」の重要性

コード内で `’.'” & angleDMS` と記述している点に注目してほしい。
Excelは優秀すぎるゆえに、`30°15’20″` のような入力を受けると、勝手に日付や数式、あるいはエラー値と解釈してセルを破壊することがある。
これを防ぎ、確実な「文字列(Text)」としてExcelに保持させるために、先頭にシングルクォートを付与して明示的にテキスト属性を強制しているのだ。これは実務自動化におけるシニアの定石である。

② モデル空間走査のパフォーマンス最適化

上記のコードでは `ModelSpace.Count` をループさせているが、図面内に数万個のエンティティが存在する場合、このループは無視できないボトルネックになる。
もしパフォーマンスが問題になる規模の図面を扱う場合は、`ModelSpace` の直接走査ではなく、`SelectionSet` と `Filter`(DXFグループコード `0` の `LINE` 指定)を用いた高速フィルタリング抽出に切り替えるべきだ。

③ COMオブジェクトの参照リーク対策

VBAにおける `CreateObject` や `ActiveDocument` の操作は、背後でCOMコンポーネントの参照カウンタを操作している。
コード内でエラーが発生した際、適切に `Set xlApp = Nothing` などを経由させないと、タスクマネージャーの裏で `excel.exe` がゾンビプロセスとして残存し続け、PCのメモリを喰らい尽くす。
必ず `On Error GoTo` を用いたクリーンアップパス(`CleanUp:` ラベル)を通す設計を徹底すること。

総括

AutoCAD VBAによる自動化の真髄は、「AutoCADが持つエンジンをどれだけ信頼し、APIに仕事をさせるか」にある。自前の複雑な計算ロジックを書く暇があるなら、ネイティブの `AngleToString` をスマートに呼び出し、残りのリソースをビジネスロジックの構築やUIの改善に充てるべきだ。

この知見を取り入れたあなたなら、もう測量データの変換ごときで悩むことはないはずだ。
さあ、このコードをあなたの開発環境に実装し、圧倒的な処理速度と堅牢性で周囲を驚かせてやりたまえ。

タイトルとURLをコピーしました