AutoCAD VBAを掌握する極限の知見:Extension DictionaryとXrecordによる高度図面メタデータ管理
AutoCAD VBAの実務において、`AcadLine`や`AcadBlockReference`といった幾何形状の操作だけで満足しているうちは、ジュニアエンジニアの域を出ない。真に大規模な図面管理システムや、外部PLM/BIMデータベースとのシームレスな連携基盤を構築する者にとって、図面オブジェクトの「内なる宇宙」を制することは必須の要件である。
今回は、図面内の全オブジェクト(または特定画層など)に隠されたカスタムメタデータ――Extension Dictionary(拡張辞書)とXrecord(拡張レコード)を網羅的に検索・抽出する極限のテクニックを解説する。
レガシーなVBA環境であっても、メモリのライフサイクルを完全に掌握し、数万オブジェクトを抱える重量級図面を瞬時にハックする方法を伝授しよう。
—
1. 拡張辞書(Extension Dictionary)とXrecordのアーキテクチャ
AutoCADの図面データベース(DwgDatabase)の裏側では、すべての図面エンティティ(`AcadEntity`)およびシンボルテーブルレコードが、独自の「拡張辞書」を保持する潜在能力を持っている。
- Extension Dictionary (`AcadDictionary`): オブジェクトに紐づくコンテナ。名前付きのキー(文字列)でエントリを管理する。
- Xrecord (`AcadXrecord`): 辞書の中に格納される実データコンテナ。AutoCADのLISPでいう「DXFグループコード」のリストをVBAから安全に構造化データとして読み書きできる。
これらを駆使すれば、図面内のブロックに「部材ID」「承認ステータス」「最終更新日時」といった非グラフィカルな属性を、属性定義(Attributes)の制限を受けずにスマートに埋め込むことが可能になる。
—
2. 実装:高速かつ安全にカスタムプロパティを全検索するVBAエンジン
以下のコードは、図面内のすべてのモデル空間エンティティを走査し、指定したキーを持つExtension Dictionary / Xrecordを再帰的かつ高速に抽出する実用的なモジュールである。
VBAにおける最大の罠である「COMオブジェクトの解放漏れによるメモリリーク」を防ぐため、すべてのオブジェクト変数に対して厳格な参照切断(`Set obj = Nothing`)を行っている点に注目してほしい。
Option Explicit
‘ ==============================================================================
‘ 処理名: 図面内全エンティティからの指定拡張辞書・Xrecord検索エンジン
‘ アーキテクトノート:
‘ 数万オブジェクトを処理する際、COMラッパーの解放漏れはAutoCADのクラッシュを
‘ 引き起こす。ループ内でのカウンタ管理と確実な参照破棄を徹底すること。
‘ ==============================================================================
Public Sub SearchCustomMetadataMaster()
Dim targetKey As String
targetKey = “SYS_META_ID” ‘ 検索したいカスタムプロパティのキー名
Dim doc As AcadDocument
Set doc = ThisDrawing
Dim modelSpace As AcadModelSpace
Set modelSpace = doc.ModelSpace
Dim ent As AcadEntity
DIm dict As AcadDictionary
Dim xrec As AcadXrecord
Dim matchCount As Long
matchCount = 0
Dim startTime As Double
startTime = Timer
Debug.Print “=== 拡張辞書検索開始: キー = [” & targetKey & “] ===”
‘ モデル空間の全エンティティを走査
Dim i As Long
For i = 0 To modelSpace.Count – 1
Set ent = modelSpace.Item(i)
‘ エラーハンドリングの局所化(削除済みやロックされたオブジェクト対策)
On Error Resume Next
‘ オブジェクトが拡張辞書を持っているか確認
If ent.HasExtensionDictionary Then
Set dict = ent.GetExtensionDictionary
‘ 指定したキーのエントリが存在するかチェック
Dim foundObj As AcadObject
Set foundObj = dict.Item(targetKey)
If Err.Number = 0 And Not foundObj Is Nothing Then
‘ 取得したオブジェクトがXrecordであるか型判定
If TypeOf foundObj Is AcadXrecord Then
Set xrec = foundObj
‘ Xrecordからデータを抽出して処理
Call ExtractAndProcessXrecordData(ent, xrec, targetKey)
matchCount = matchCount + 1
End If
End If
‘ エラー状態のリセット
Err.Clear
End If
‘ — 致命的:メモリ最適化のための明示的参照解放 —
Set foundObj = Nothing
Set xrec = Nothing
Set dict = Nothing
Set ent = Nothing
On Error GoTo 0
Next i
Debug.Print “=== 検索終了 (処理時間: ” & Format(Timer – startTime, “0.00秒”) & ” ) ===”
Debug.Print “一致したオブジェクトの総数: ” & matchCount & ” 件”
‘ ルートオブジェクトの解放
Set modelSpace = Nothing
Set doc = Nothing
End Sub
‘ ==============================================================================
‘ 内部プロシージャ: XrecordからDXFデータ(データ型と値)を安全に抽出する
‘ ==============================================================================
Private Sub ExtractAndProcessXrecordData(ByRef ent As AcadEntity, ByRef xrec As AcadXrecord, ByVal keyName As String)
Dim dataType As Variant
Dim dataValue As Variant
‘ Xrecordのデータを取得 (VBのArrayとして返される)
xrec.GetXRecordData dataType, dataValue
If IsArray(dataValue) Then
Dim j As Long
Dim infoLog As String
infoLog = “Handle: ” & ent.Handle & ” | Type: ” & ent.ObjectName & ” | Key: ” & keyName
‘ Xrecordはグループコードのペアの配列を持つ
For j = LBound(dataValue) To UBound(dataValue)
‘ 例として文字列データ(グループコード1など)をキャプチャ
infoLog = infoLog & ” | Val[” & j & “]: ” & CStr(dataValue(j))
Next j
‘ イミディエイトウィンドウに出力(実務ではここで外部DBやCSVへ書き出す)
Debug.Print infoLog
End If
End Sub
—
3. シニアエンジニアが押さえるべき「極限の知見」
① AutoCAD VBAにおけるメモリリークのメカニズム
VBAの裏側では、AutoCADのCOMオブジェクト(C++で書かれたObjectARXの実体)とVBAのラッパーオブジェクトが1対1で生成される。
ループ内で `Set ent = modelSpace.Item(i)` を繰り返すとき、前の参照を明示的に `Set ent = Nothing` で切断しないと、AutoCADプロセス側の参照カウンタが下がらず、数千回まわっただけで数百MBのメモリがリークする。
特に大規模図面(100MB超)を扱う場合、この解放漏れはAutoCAD自体のフリーズ(致命的な例外)を誘発する最大の原因となる。
② HandleとObject IDの使い分け
コード内で `ent.Handle` を取得している点に注目してほしい。
AutoCADのメモリ内ポインタである `ObjectID` は図面セッションを閉じると無効化されるが、`Handle`(16進数の文字列)は図面ファイルを保存・再オープンしても不変である。
外部システム(Web APIやRDBなど)と連携するメタデータ検索基盤を構築する場合、オブジェクトの特定には必ずこの `Handle` をキーとして利用すべきだ。
—
4. システム間連携への昇華:VBAから外部DBへのブリッジ
このスクリプトで抽出した `Handle` と `Xrecord` 内のカスタムプロパティを、ADO(ActiveX Data Objects)経由でMicrosoft SQL ServerやPostgreSQLに非同期でバルクインサートする構造を構築すれば、AutoCADは単なる「図面エディタ」から「リッチなBIM/CIMデータベースのフロントエンド」へと昇華する。
レガシーと侮られがちなVBAであっても、オブジェクトモデルのライフサイクルとメモリ管理の物理法則を理解していれば、現代のモダンなエンタープライズシステムと伍して戦う堅牢な自動化基盤を構築できる。
妥協なきコードで、あなたの図面管理を次の次元へ引き上げろ。
