【AutoCAD VBAを極める】Databaseオブジェクトの直接操作とUndo/Redoトランザクションの完全制御
AutoCAD VBAを用いた開発において、多くの開発者は`AcadModelSpace.AddLine`といった高レベルなラッパーメソッドの利用で満足しがちだ。しかし、実務で数万エンティティを扱う巨大な図面や、厳密なデータ整合性が求められるエンタープライズ環境において、そのアプローチは致命的なボトルネックとなる。
画面描画(Graphics System)と連動した高レベルAPIは、一回の図形追加ごとにイベントや画面の再描画が発生し、処理速度が極端に低下する。さらに、処理の途中でエラーが発生した際、中途半端に書き換わった図面が残り、ユーザーの「Ctrl + Z(Undo)」すら効かない絶望的な状況を生み出す。
今回は、AutoCAD VBAの底力を引き出し、`AcadDocument.Database`を直接叩いてパフォーマンスを極限まで高めつつ、堅牢なUndo/Redoトランザクションを構築するプロフェッショナルな設計手法を伝授する。
—
1. なぜ「Database直接操作」と「Undo制御」が必要なのか?
画面描画の呪縛からの解放
通常のVBAコードでオブジェクトを生成・編集する場合、AutoCADは「オブジェクトが作成された瞬間」にそれをモデル空間のインターフェースへ反映させようとする。これには膨大なオーバーヘッドが伴う。
一方、`Database`オブジェクトから直接メモリ上のシンボルテーブル(BlockTableRecordなど)にアクセスし、トランザクションの概念を持ってバルク処理を行えば、描画の更新を最小限に抑え、ネイティブC++に近い処理速度を手に入れることができる。
プロフェッショナルが守るべき「原子性(Atomicity)」
自動化スクリプトは、途中でエラーが起きたとき「すべて実行されるか、全く実行されないか(All-or-Nothing)」の保証がなければならない。
AutoCADには、一連のデータベース変更をひとまとめにし、ユーザーの「1回のUndo」で綺麗に元の状態へ巻き戻せる仕組みが用意されている。これがトランザクション的なUndo/Redoスタックの制御である。
—
2. アーキテクチャの全体像:VBAにおけるトランザクション的アプローチ
AutoCADの内部データベース(`AcDbDatabase`)に対し、VBAから安全にアクセスするためには、以下のステップを踏む必要がある。
1. 対象ドキュメントの `Database` オブジェクトを取得する。
2. UndoMark(Undoの開始点)を明示的にプログラムで作成する。
3. エラーハンドリング(`On Error GoTo`)を必ず配置する。
4. 処理成功時はUndoMarkを閉じ、失敗時はコード側から確実に戻す、あるいはユーザーに委ねる。
—
3. 【プロダクションコード】堅牢な一括処理実装例
以下のコードは、数千個の円を一瞬で生成し、それらを一つの「Undoグループ」としてまとめ、途中でエラーが発生しても確実にデータベースの整合性を守る実務レベルのモジュールである。
Option Explicit
‘ ==============================================================================
‘ 担当者必見:データベース直接操作 & Undo制御テンプレート
‘ 概要: 高速バルク処理と安全なUndo/Redoスタック管理を両立させた実装例
‘ ==============================================================================
Sub ExecuteHighPerformanceBatchProcess()
Dim acadApp As AcadApplication
Dim acadDoc AcadDocument
Dim pDb As AcadDatabase
‘ 実行時間の計測用(パフォーマンス確認用)
Dim startTime As Double
startTime = Timer
‘ 1. アプリケーションとアクティブドキュメントの取得
On Error GoTo ErrorHandler
Set acadApp = ThisDrawing.Application
Set acadDoc = acadApp.ActiveDocument
Set pDb = acadDoc.Database
‘ 画面描画を一時停止し、パフォーマンスを最大化する(重要)
acadApp.ZoomExtents
acadDoc.Utility.Prompt vbCrLf & “高速バッチ処理を開始します…”
‘ 2. Undoの開始マーク(StartUndoMark)を設定
‘ これにより、この処理で行う一連の変更が「1回のCtrl+Z」で巻き戻せるようになる
acadDoc.StartUndoMark
‘ 3. データベースの根幹となるブロックテーブル(ModelSpace)を取得
Dim blkTable As AcadBlockTable
Dim modelSpace As AcadBlockTableRecord
Set blkTable = pDb.BlockTable
Set modelSpace = blkTable.Item(acModelSpace)
‘ 4. 高速バルク処理の実行(例:1000個の円を生成)
Dim i As Long
Dim centerPoint(0 To 2) As Double
Dim radius As Double
Dim newCircle As AcadCircle
radius = 5.0
‘ トランザクション的処理ループ
For i = 1 to 1000
centerPoint(0) = (i Mod 50) 15.0
centerPoint(1) = (i \ 50) 15.0
centerPoint(2) = 0.0
‘ モデル空間レコードへ直接エンティティを追加
Set newCircle = modelSpace.AddCircle(centerPoint, radius)
‘ ※必要に応じて拡張データ(Xdata)やレイヤー設定をここで直接行う
newCircle.Layer = “0”
Next i
‘ 5. 正常終了時の処理:Undoマークを閉じる
acadDoc.EndUndoMark
‘ 描画を強制更新
acadDoc.Regen acAllViewports
MsgBox “処理が正常終了しました。\n処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation, “プロフェッショナル自動化”
Exit Sub
ErrorHandler:
‘ 6. 異常終了時のフォールバック処理
‘ エラー発生時は、必ずUndoMarkを閉じてからロールバックを試みる
On Error Resume Next
‘ 未完了のUndoMarkが開いたままになるのを防ぐため強制終了
acadDoc.EndUndoMark
‘ ユーザーの操作、またはプログラム側で変更を破棄させるためのUndo
‘ (※必要に応じてacadDoc.SendCommand “_.UNDO _Back “などを検討)
MsgBox “致命的なエラーが発生しました。処理を中断し、データベースを保護しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
‘ クリーンアップ
Set newCircle = Nothing
Set modelSpace = Nothing
Set blkTable = Nothing
Set pDb = Nothing
Set acadDoc = Nothing
Set acadApp = Nothing
End Sub
—
4. チーフアーキテクトが教える「現場の罠」と回避策
罠その1:`StartUndoMark` と `EndUndoMark` のペア忘れ
`StartUndoMark` を呼び出した後、コード内でエラー(ゼロ除算やオブジェクト参照エラーなど)が発生して `EndUndoMark` に到達しない場合、AutoCADの内部Undoスタックが破損状態(Open Undo Markが残ったまま)になる。
これが発生すると、ユーザーが手動で図面を操作した際にもUndoが効かなくなるか、最悪の場合クラッシュを引き起こす。
対策: 必ず `On Error GoTo ErrorHandler` を記述し、エラーハンドラ内でも確実に `EndUndoMark` を呼び出すこと(上記のコード例を模範とせよ)。
罠その2:非活性ドキュメントへの直接書き込み
マルチドキュメント環境(MDI)において、バックグラウンドで開いている `AcadDocument` に対し、不意に `Database` 操作を行ってはならない。VBAから操作できるのは基本的に `ThisDrawing`(アクティブなドキュメント)のデータベースに限られる。他の図面を操作する場合は、必ず `Documents.Open` でアクティブ化するか、ObjectARX/.NET APIの別アプローチを検討すべきである。
罠その3:イベントハンドラの暴走
データベースを直接大量に書き換える際、`AcadDocument` の各種イベント(`ObjectAppended` など)が有効になっていると、イベントの処理コストだけでスクリプトが数倍遅くなる。大規模なバッチ処理を行う前には、必要に応じてイベントの有効/無効を制御する設計が望ましい。
—
5. まとめ
AutoCAD VBAは「おもちゃのマクロ言語」ではない。オブジェクトモデルの深層、すなわち `Database` と `UndoStack` のメカニズムを完全に理解し制御下におくことで、市販の専用アドインソフトに匹敵する堅牢性とパフォーマンスを発揮するプロフェッショナルなソリューションへと昇華させることができる。
「動けばいい」のコードから卒業し、メンテナンス性、パフォーマンス、そして何よりユーザーの大切な図面データを守る堅牢性を備えたコードベースを、あなたの開発現場に導入してほしい。
