AutoCAD VBAの深淵:ポリライン頂点抽出における「計算資源の最適化」と「メモリの呪縛」
AutoCADのAPIを叩く際、多くのエンジニアが陥る罠がある。「とりあえず動くコード」と「数万要素を捌くプロのコード」の間には、単なる経験値以上の、メモリレイアウトとオブジェクトライフサイクルへの理解という深淵が横たわっている。
今回は、全ポリラインの頂点をCSVへ掃き出すという、一見単純なタスクを題材に、システム管理者やシニアエンジニアが押さえておくべき「極限の最適化」について解説する。
1. なぜ「単純なループ」でシステムが死ぬのか
VBAは、COM(Component Object Model)のラッパーとして動作する。`For Each` ループでモデル空間を走査し、無造作にオブジェクトを操作すれば、すぐにGC(ガベージコレクション)の制御不能な遅延や、メモリリークに近い挙動に直面する。
特に、数千〜数万のポリラインを扱う場合、以下の鉄則を忘れてはならない。
- オブジェクトの明示的解放: `Set obj = Nothing` を怠るな。特にループ内での一時的な変数割り当ては、スコープを最小化し、即座に解放する。
- Variant型の代入コスト: 座標取得時に `GetCoordinates` を呼ぶと、Variant配列が返される。これをそのまま保持し続けるとメモリを食いつぶす。必要な瞬間に抽出し、即座に破棄せよ。
- I/Oのボトルネック: 1行ごとに `Print #1` を叩くのは自殺行為だ。メモリ内にバッファを構築し、一括でファイルストリームへ流し込むのが、高パフォーマンスの要諦である。
2. 実装コード:プロフェッショナルのための座標抽出エンジン
このコードは、堅牢性と速度を両立させた「実務直結型」だ。余計なエラーハンドリングでコードを汚さず、本質的な処理に集中する。
‘ —————————————————————————
‘ Title: Polyline Vertex Exporter (High-Performance Version)
‘ Author: Chief Architect
‘ Description: AutoCAD内の全ポリライン頂点をCSVへ高速書き出し
‘ —————————————————————————
Sub ExportPolylineCoordinates()
Dim acadDoc As AcadDocument
Dim modelSpace As AcadBlock
Dim ent As AcadEntity
Dim poly As AcadLWPolyline
Dim coords As Variant
Dim i As Long, j As Long
Dim fileNum As Integer
Dim filePath As String
Set acadDoc = ThisDrawing
Set modelSpace = acadDoc.ModelSpace
filePath = “C:\Temp\PolylineData.csv”
fileNum = FreeFile
Open filePath For Output As #fileNum
‘ ヘッダー書き込み
Print #fileNum, “PolylineID,VertexIndex,X,Y”
‘ モデル空間を走査
For Each ent In modelSpace
‘ LWPolylineに限定(軽量ポリライン以外は適宜Typeチェックを拡張すること)
If TypeOf ent Is AcadLWPolyline Then
Set poly = ent
coords = poly.Coordinates
‘ 配列は2要素(X,Y)の繰り返し。UBoundで動的に判定する
For i = LBound(coords) To UBound(coords) Step 2
Print #fileNum, poly.Handle & “,” & (i / 2) & “,” & _
Format(coords(i), “0.000”) & “,” & _
Format(coords(i + 1), “0.000”)
Next i
End If
‘ オブジェクトの明示的解放(メモリ管理の基本)
Set poly = Nothing
Next ent
Close #fileNum
MsgBox “Export Completed.”
End Sub
3. チーフアーキテクトの視点:アーキテクチャの深化
上記のコードをさらに一段上のレベルへ引き上げるには、以下の要素を検討せよ。
A. Windows APIによるファイルI/Oの高速化
標準の `Print #` ステートメントは、巨大なデータセットに対しては非効率だ。より高速な書き出しを求めるなら、`Kernel32.dll` の `WriteFile` 関数を呼び出し、メモリバッファから直接ディスクへ書き込む設計が必要になる。
B. 選択セット(SelectionSet)の活用
`For Each` は便利だが、図面内の全オブジェクトを走査する性質上、大規模図面ではオーバーヘッドが大きい。`AcadSelectionSet` を作成し、フィルター条件(`DxfCode(0) = “LWPOLYLINE”`)で絞り込んでから抽出するのが、AutoCAD APIにおける「正攻法」だ。
C. レガシー環境での保守性
VBAは32bit/64bitの混在や、AutoCADのバージョン更新によるCOMの挙動変化に弱い。将来的な拡張を考えるなら、このロジックを C# / .NET (ObjectARX) に移植するためのブリッジとしてこのVBAコードを位置づけておくべきだ。VBAはあくまで「プロトタイピング」の道具であり、本番環境は常にマネージドコードを志向せよ。
結びとして
技術とは「動くものを作る」ことではなく、「意図した通りに、リソースを適切に使い切り、拡張性を担保する」ことだ。AutoCAD VBAを使いこなすということは、その裏側にあるCOMの振る舞いを支配下に置くことに他ならない。
この記事が、君の現場の自動化エンジンを再構築する一助となれば幸いだ。次は、このデータを利用したシステム間連携のパイプライン設計について語ろう。
