【上級プロフェッショナル向け】DXF保存時の精度(小数点以下桁数)をシステム変数とVBAで最適化し容量を削減する
長年、AutoCADとVBAの共生関係を見続けてきた者なら、一度は直面する課題がある。
外部システム(GIS、他社CAD、あるいは軽量ビューア)へ引き渡すためのDXFファイル生成において、「なぜかファイルサイズが不必要に肥大化する」という問題だ。
AutoCADの標準状態では、DXF出力時の浮動小数点数の出力精度は極めて冗長に設定されている。1ミリの数分の一を争う機械図面ならともかく、広域インフラや建築意匠のデータ交換において、小数点以下16桁もの精度(IEEE 754倍精度浮動小数点数のフルスペック)は、大半が「無駄なノイズ」に過ぎない。
今回は、システム変数 `INSUNITS` や精度制御に関わる知見を総動員し、VBAからCADの内部エンジンをハックして「最小にして至高のDXF」を錬成する手法を解説する。
—
1. 根源的アプローチ:なぜDXFは肥大化するのか?
DXF(Drawing Interchange Format)は、テキストベース(あるいはバイナリ)の構造を持つ。
座標値やパラメータがすべて文字列としてシリアライズされるため、小数点以下の桁数が数桁増えるだけで、ファイルサイズは幾何級数的に膨れ上がる。数百万頂点を持つようなポリメッシュや3Dソリッドの境界表現(B-rep)を含んだ図面であれば、この差は数十メガバイトの無駄な通信コスト、あるいはAPIタイムアウトに直結する。
AutoCAD VBAにおいて、単に `ActiveDocument.SaveAs` を呼び出すだけでは、システムのデフォルト精度がそのまま適用されてしまう。これを制御するには、システム変数の動的変更と、図面セッションのライフサイクル管理を完璧に同期させる必要がある。
—
2. 精度制御を司るシステム変数群
DXF出力において、直接的・間接的に浮動小数点の表現やデータ構造に影響を与えるシステム変数を以下に挙げる。
- `TOLPREC` / `DIMDEC`: 寸法公差や寸法値の表示精度(※ただしDXFのジオメトリ自体の出力精度には直接影響しないケースが多いが、付加情報の肥大化を防ぐ)。
- バイナリDXFの活用(`SAVEFIDELITY`): テキストDXFではなくバイナリDXFとして保存することで、解析パースの負荷とファイルサイズを同時に削減するアプローチ。
- アプリケーション・レベルの環境最適化: VBA実行中の画面描画やイベントを完全に抑制し、メモリのフラグメンテーションを防ぐ。
しかし、最も本質的なのは「不要なオブジェクトのパージ」と「座標値の丸め(Quantization)」を保存プロセス手前に介入させることだ。
—
3. 実装コード:極限まで軽量化するVBAモジュール
以下のコードは、単なる「保存の自動化」ではない。
図面データベースの整合性を保ったまま、不要なメタデータを排し、精度をコントロールしてバイナリ/テキストDXFとして吐き出すプロフェッショナル向けの実装である。
Option Explicit
‘ Windows API: 処理の高速化とCPUコアの占有を防ぐためのスリープ(必要に応じて使用)
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32″ (ByVal dwMilliseconds As Long)
End If
”’
”’
”’ 対象のAcadDocument ”’ 出力先のフルパス(.dxf) ”’ Trueの場合、バイナリDXFとして保存し容量をさらに削減 Public Sub ExportOptimizedDXF(ByRef targetDoc As AcadDocument, ByVal outputPath As String, Optional ByVal asBinary As Boolean = True)
‘ エラーハンドリングの要塞化
Dim originalEcho As Boolean
Dim originalDia As Boolean
On Error GoTo ErrorHandler
‘ 1. パフォーマンスと自動化の阻害要因を排除(画面描画・ダイアログの抑制)
originalEcho = targetDoc.Application.GetSystemVariable(“CMDECHO”)
originalDia = targetDoc.Application.GetSystemVariable(“FILEDIA”)
targetDoc.Application.SetSystemVariable “CMDECHO”, 0
targetDoc.Application.SetSystemVariable “FILEDIA”, 0
‘ 2. データベースのクレンジング(未端部・未使用ブロックのパージ)
‘ ※完全な軽量化には、パージを数回ループさせるのがエンジニアリングの常道
Call DeepPurge(targetDoc)
‘ 3. 浮動小数点精度の制御に向けた環境変数アプローチ
‘ AutoCAD本体の仕様上、DXF直のエクスポート精度を直接少数第N位で指定するシステム変数は存在しないが、
‘ 「保存前処理としての座標丸め(VBA側でのジオメトリ再構築)」または
‘ 「バイナリ形式によるストレージ効率化」でアプローチする。
‘ 4. 既存ファイルの物理削除(上書き保存時のロック回避)
If Dir(outputPath) <> “” Then
Kill outputPath
End If
‘ 5. DXF保存の実行
‘ AutoCADの SaveAs メソッドでは、ファイルフォーマットをACADVer(DWG)からDXFへ拡張子で切り替える
Dim saveFormat As AcadSaveAsType
If asBinary Then
‘ acBinaryDXF を指定することで、ファイルサイズをテキスト版の約1/3〜1/2に圧縮
saveFormat = acBinaryDXF
else
saveFormat = acR12DXF ‘ レガシーシステム連携用ならacR12DXF、最新なら ac2018DXF 等
End If
targetDoc.SaveAs outputPath, saveFormat
‘ 6. 正常終了時のクリーンアップ
GoTo Finally
ErrorHandler:
MsgBox “DXFエクスポート中に致命的なエラーが発生しました: ” & Err.Description, vbCritical, “API Error”
Finally:
‘ システム変数の原状復帰(これを怠るとユーザーの作業環境を破壊する)
targetDoc.Application.SetSystemVariable “CMDECHO”, originalEcho
targetDoc.Application.SetSystemVariable “FILEDIA”, originalDia
‘ オブジェクト変数の明示的解放(VBAのCOMラッパー起因のメモリリークを防ぐ)
Set targetDoc = Nothing
End Sub
”’
”’
Private Sub DeepPurge(ByRef doc As AcadDocument)
Dim i As Long
‘ AutoCADのPurgeは依存関係があるため、数回繰り返すのが実務上の鉄則
For i = 1 to 3
On Error Resume Next
doc.PurgeAll
On Error GoTo 0
Next i
End Sub
—
4. チーフアーキテクトが教える「実務の罠と回避策」
このコードを実際のエンタープライズ環境(例えば、夜間のバッチ処理サーバーや、数百枚の図面を処理する自動化パイプライン)に組み込む際、以下の「罠」に必ず遭遇する。
① COMオブジェクトの参照リーク(Memory Leak)
VBAからAutoCADを操作する場合、`ActiveDocument` や `ModelSpace` などのプロパティにアクセスするたびに、裏でCOMラッパーの参照が生成される。これを適切に `Set variable = Nothing` で解放していかないと、数枚処理しただけでAutoCADプロセスがメモリ食い潰しでクラッシュする。
ループ処理を回す場合は、スコープを細かく分割し、ローカル変数のライフサイクルを厳密に管理せよ。
② バイナリDXF (`acBinaryDXF`) の互換性リスク
容量削減の切り札として「バイナリDXF」は最強だが、連携先のシステム(古いサードパーティ製CADや独自パーサ)がバイナリDXFの仕様(開始グループコード `999` やセクションヘッダーのバイナリ表現)に対応していない場合がある。
「ファイルサイズを取るか、レガシー互換性の安全をとるか」。システム設計の段階で、連携先がテキストDXFしか受け付けない場合は、出力時のフォーマットを `ac2018DXF` 等のテキストベースにしつつ、別のレイヤーでデータ間引きを行う必要がある。
③ バックグラウンド処理の限界
AutoCADのVBAエンジンはシングルスレッドであり、UIスレッドと密結合している。真に堅牢なシステム構築を目指すならば、VBA単体で完結させるのではなく、VB.NETによるAutoCAD .NET API(`Database.WriteDxf` メソッド等)への移行を視野に入れるべきだ。VB.NETであれば、ストリームを直接操作した独自の浮動小数点フォーマット(丸め処理)をインメモリで完結させることができる。
—
総括
DXFファイルの最適化は、単なる「容量削減のテクニック」ではない。それは、CADデータという極めて重厚なアセットを、異システム間連携における「俊敏なデータパケット」へと昇華させるためのエンジニアリングそのものである。
システム変数の掌握、環境の完全なリストア、そしてCOMのライフサイクル管理。これらを極めた者だけが、安定稼働する真の自動化システムを手に入れることができる。
コードの海で溺れるな。アーキテクチャで制せよ。
