AutoCAD VBAの死角:`Regen`の暴走と描画パイプラインの制約
AutoCADのAPIを叩く際、多くのジュニアエンジニアが陥る罠がある。ループ処理の中で「とりあえず動いたから」と`Update`メソッドや`Regen`を乱発することだ。
AutoCADの描画エンジンは、強力だが非常に繊細だ。特にCOMベースのVBAからオブジェクトを大量生成する場合、描画スレッドとの競合は致命的なパフォーマンス低下を招く。本稿では、レガシーかつ現代の巨大プロジェクトでも通用する、描画最適化の極致を解説する。
—
1. 描画負荷の正体:なぜ`Regen`を呼んではいけないのか
`AcadDocument.Regen`は、データベースを再構築し、画面の再描画を強制する重い処理だ。これをループ内で行うということは、1,000個の円を描くたびに、CPUとGPUに「これまでの作業をすべて一旦捨てて、全オブジェクトを再計算・再レンダリングせよ」と命じているに等しい。
プロの自動化において、「描画はコストである」という認識を徹底せよ。
描画抑制の基本原則
1. `Application.ScreenUpdating` (非対応の呪縛): Excel VBAとは異なり、AutoCADには単一のフラグで描画を止める魔法は存在しない。
2. `SysVar`の操作: `CMDECHO`や`PICKFIRST`、さらには`REGENMODE`を制御し、AutoCADの「気を利かせた再計算」を物理的に封じ込める必要がある。
—
2. 極限のパフォーマンスを実現する最適化コード
以下は、数万単位のオブジェクトを一括生成する際に用いる、私が現場で常用しているテンプレートだ。
Public Sub OptimizedEntityCreation()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
‘ 実行環境の確保
Set acadApp = ThisDrawing.Application
Set acadDoc = ThisDrawing
‘ システム変数による自動再描画の完全遮断
‘ REGENMODEを0に設定し、バックグラウンドでの再描画を殺す
Dim oldRegenMode As Integer
oldRegenMode = acadDoc.GetVariable(“REGENMODE”)
acadDoc.SetVariable “REGENMODE”, 0
‘ トランザクション処理の代替(VBAの場合、Application.BeginUndoGroupが必須)
acadApp.BeginUndoGroup
On Error GoTo Cleanup
‘ ここで大量のオブジェクト生成ループを実行
Dim i As Long
For i = 1 To 10000
‘ 明示的なUpdateは絶対にコールしないこと
Call CreateEntity(acadDoc)
Next i
‘ 最後に一度だけ再描画を行う
acadDoc.Regen acActiveViewport
Cleanup:
‘ 異常終了時でもシステム変数を戻すこと(極めて重要)
acadDoc.SetVariable “REGENMODE”, oldRegenMode
acadApp.EndUndoGroup
If Err.Number <> 0 Then
MsgBox “エラー発生: ” & Err.Description, vbCritical
End If
End Sub
—
3. メモリ解放のアーキテクト的思考
VBAはガベージコレクションが脆弱だ。大量のオブジェクトを扱う際、COMポインタの解放を怠ると、AutoCAD本体のメモリリークを誘発し、長時間稼働のシステムでは「数時間後にクラッシュする」という最悪の結果を招く。
実践的メモリ管理の鉄則
- オブジェクト変数の明示的破棄: ループ内で使用する一時的な`AcadEntity`変数は、ループの末尾で必ず `Set entity = Nothing` を実行すること。
- セレクションセットの管理: `AcadSelectionSets`に生成した名前付きコレクションは、使用後に必ず `Delete` メソッドで明示的に破棄すること。これを忘れると、次回のマクロ実行時に名前重複エラーで沈黙する。
‘ 厳格なメモリ管理の例
Dim ent As AcadEntity
For i = 1 To 10000
Set ent = acadDoc.ModelSpace.AddLine(pt1, pt2)
‘ 処理…
Set ent = Nothing ‘ 明示的解放
Next i
—
4. チーフアーキテクトからの提言:APIの向こう側へ
AutoCAD VBAは、現代の.NET APIやObjectARXに比べればレガシーな技術だ。しかし、この「泥臭い制御」こそが、システムの堅牢性を担保する。
もしあなたが、数百万件のオブジェクトを扱うような極限環境に身を置いているのなら、VBAの限界を認め、`ObjectARX`や`.NET API`の`Transaction`オブジェクトへの移行を検討すべきだ。VBAはあくまでフロントエンドのトリガーであり、重厚な計算は`.NET`のマネージコードで行う――これこそが、現在のCAD開発における「正解」である。
だが、VBAでやるなら、せめて`Regen`を無闇に叩くのはやめろ。コードは、機械に対する敬意を持って書くものだ。それが、職人の矜持というものだろう。
