【テクニカル・上級編】【実務中級】図面内の全ブロック定義(Block Definition)を検索し、そのプロパティ(挿入尺度、回転角度など)を一覧化する – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:図面内ブロック定義の全抽出とメモリ最適化のアーキテクチャ

AutoCAD VBAにおけるオブジェクトモデルの挙動は、一般的なMicrosoft Office VBAのそれとは一線を画す。背後で強固なC++のGeometrical Engineが稼働しており、COMラッパーであるVBAから操作する際には、オブジェクトのライフサイクルとメモリ管理のメカニズムを完全に理解していなければならない。

今回は、図面内に存在するすべてのブロック定義(Block Definition)を走査し、そのプロパティを徹底的に抽出し一覧化する実務中級以上のソリューションを解説する。単に動くコードを示すのではない。数百万ライン規模のレガシー図面をクラッシュさせずに処理するための、シニアエンジニア必携のメモリ最適化とパフォーマンスチューニングの極意を伝授する。

1. AutoCADオブジェクトモデルの深層:Blocksコレクションの罠

多くの初学者は、図面内のブロックを操作する際に `ActiveSelectionSet` や `ModelSpace` 内の `acBlockReference`(挿入された図形)を走査しがちだ。しかし、真の「ブロック管理」において対象とすべきは、図面データベースの心臓部である `ThisDrawing.Blocks` コレクション、すなわちブロック定義そのものである。

ブロック参照(BlockReference)とブロック定義(Block)の決定的違い

  • ブロック参照(AcadBlockReference): モデル空間やレイアウト空間に配置された「インスタンス」。座標、回転角、スケールを持つ。
  • ブロック定義(AcadBlock): データベースに格納された「設計図(クラス定義)」。内部に保持する線分や円などのエンティティの集合体であり、レイアウトとは独立して存在する。

全ブロック定義を走査する際、AutoCAD特有の「匿名ブロック(Anonymous Blocks:寸法図形やダイナミックブロックが内部生成する一時的なもの)」や「レイアウト空間そのものを表すブロック」が混入する。これらを適切にフィルタリングしつつ、メモリリークを回避しながら走査するアーキテクチャが必要となる。

2. 実装:高速かつ堅牢なブロック定義一覧化エンジン

以下のコードは、実務の現場で即座に稼働する、最適化されたVBAプロシージャである。新規図面を作成し、抽出結果を綺麗に表形式でシート状(Excel連携を想定、またはAutoCAD上のテキスト・CSV出力)に出力するための基盤となる。

Option Explicit

‘ ==============================================================================
‘ 処理名 : ExportBlockDefinitionsToCSV
‘ 概要 : 図面内の全ブロック定義を走査し、そのプロパティをCSVファイルへ極限まで
‘ 高速にエクスポートする。
‘ 備考 : 匿名ブロックを除外し、メモリ最適化(オブジェクトの即時解放)を徹底。
‘ ==============================================================================
Public Sub ExportBlockDefinitionsToCSV()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
Dim blkDef As AcadBlock
Dim ent As AcadEntity

Dim fso As Object
Dim ts As Object
Dim csvPath As String
Dim blockCount As Long
Dim entCount As Long
Dim isAnonymous As Boolean
Dim basePoint(0 To 2) As Double

‘ 1. 実行コンテキストの安全な取得 (Early Bindingを推奨)
On Error Resume Next
Set acadApp = ThisDrawing.Application
Set acadDoc = ThisDrawing.ActiveDocument
If Err.Number <> 0 Then
MsgBox “AutoCADアプリケーションまたはドキュメントの取得に失敗しました。”, vbCritical, “致命的エラー”
Exit Sub
End If
On Error GoTo 0

‘ 2. 出力先パスの決定 (デスクトップにタイムスタンプ付きCSVを生成)
csvPath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\BlockDefinitions_” & Format(Now, “YYYYMMDD_HHNNSS”) & “.csv”

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set ts = fso.CreateTextFile(csvPath, True, True) ‘ Unicode (UTF-16) で書き込み

‘ CSVヘッダーの書き込み
ts.WriteLine “ブロック名,エンティティ数,基準点X,基準点Y,基準点Z,IsLayout,IsAnonymous,Path”

‘ 3. パフォーマンス向上のための画面描画・イベント抑制
acadApp.ScreenUpdating = False

‘ 4. Blocksコレクションの走査 (極限のメモリ管理)
For Each blkDef In acadDoc.Blocks
‘ 匿名ブロック(”で始まるもの)や外部参照の不要な深入りをスキップ
isAnonymous = (Left$(blkDef.Name, 1) = “”)

If Not isAnonymous And Not blkDef.IsLayout Then
‘ 基準点の取得
basePoint(0) = blkDef.Origin(0)
basePoint(1) = blkDef.Origin(1)
basePoint(2) = blkDef.Origin(2)

‘ ブロック内に含まれるエンティティ数を計測
entCount = blkDef.Count

‘ CSV行の組み立て
ts.WriteLine “””” & blkDef.Name & “””,” & _
entCount & “,” & _
basePoint(0) & “,” & _
basePoint(1) & “,” & _
basePoint(2) & “,” & _
IIf(blkDef.IsLayout, “True”, “False”) & “,” & _
IIf(isAnonymous, “True”, “False”) & “,” & _
“””” & blkDef.Path & “”””

blockCount = blockCount + 1
End If

‘ COMオブジェクトの参照を明示的に解放(VBAガベージコレクタの負荷軽減)
Set blkDef = Nothing
Next blkDef

‘ 5. クリーンアップ
ts.Close
Set ts = Nothing
Set fso = Nothing

acadApp.ScreenUpdating = True

MsgBox “ブロック定義の抽出が完了しました。” & vbCrLf & _
“抽出件数: ” & blockCount & ” 件” & vbCrLf & _
“出力先: ” & csvPath, vbInformation, “処理完了”

ErrorHandler_Exit:
‘ 異常終了時の確実な復旧
If Not acadApp Is Nothing Then acadApp.ScreenUpdating = True
Exit Sub
End Sub

3. シニアエンジニアが実践すべき「極限の知見」とパフォーマンスチューニング

上記のコードを単なる「動くサンプル」で終わらせず、エンタープライズ環境(大規模プラント図面や建築統合図面)に耐えうるものにするための設計思想を解説する。

① COMオブジェクトの明示的解放(`Set ◯ = Nothing` の徹底)

VBAはCOMオブジェクトを自動解放すると言われているが、それは単一スクリプトの話であって、数千・数万回ループを回すAutoCADオブジェクトモデルにおいては完全に神話である。
`For Each` ループ内で `AcadBlock` などのCOMラッパーをポインタ参照し続けると、背後のARX(AutoCAD Runtime Extension)メモリスペースとの間で参照カウントのリークが発生し、最悪の場合はAutoCAD自体がメモリ不足(Fatal Error)で強制終了する。
ループの最後で必ず `Set blkDef = Nothing` を実行し、参照を切断することが極限環境における鉄則である。

② `ScreenUpdating = False` による描画エンジンへの負荷遮断

AutoCADは、VBAからのオブジェクト参照や走査が発生した際、内部のグラフィックデータベースと同期しようと画面の再描画やキャッシュの検証を行おうとする場合がある。
処理の開始直前で `acadApp.ScreenUpdating = False` をかけ、終了時に `True` に戻すことで、GUIスレッドの無駄な割り込みを防ぎ、処理速度を最大で数倍から数十倍に跳ね上げることが可能だ。

③ 匿名ブロック(Anonymous Blocks)の厳格な除外

AutoCAD内部では、寸法線(Dimension)やハッチング、ダイナミックブロックのステート管理のために `U1`, `Model_Space` といったシステム予約のブロック定義が大量に生成される。
これらを意図せず処理対象に含めてしまうと、一覧の品質が著しく低下するだけでなく、予期せぬ例外エラーを引き起こす。先頭文字が “ であるかを判定する `Left$(blkDef.Name, 1) = “”` によるガード条件は、実務において必須のイディオムである。

4. システム間連携への拡張:VBAから.NET / APIへのブリッジング

VBAはレガシーな開発環境と揶揄されがちだが、COMオートメーションサーバーとしてのAutoCAD APIは依然として強力だ。しかし、より高度なJSONデータの入出力、外部データベース(PostgreSQLやOracle)への直接接続、マルチスレッド処理が必要な場合は、VBA単体では限界が訪れる。

その場合のシニアアーキテクトとしての布石はこうだ:
1. VBAを「軽量なランチャー・UI層」として割り切る。
2. 重たい幾何学的解析や外部API連携、データベースバルクインサートは、VB.NET(Class Library)によるAutoCAD .NET API(Managed Wrapper)で実装する。
3. VBAから `CreateObject` や COM Interop を経由して .NET製のアセンブリを呼び出す。

このアーキテクチャを採用することで、レガシーな社内VBA資産を活かしつつ、内部エンジンをモダンな.NET環境へシームレスに移行していくことが可能となる。

総括

AutoCAD VBAを極めるとは、単にメソッドやプロパティの羅列を覚えることではない。AutoCADという巨大なC++ベースのCADエンジンの上に構築されたCOMのライフサイクルをコントロールし、メモリの脈動を感じ取りながら堅牢なコードを組み上げる作業そのものである。

今回のブロック定義抽出エンジンの知見をあなたの開発環境に組み込み、日々の図面管理・自動化パイプラインを次の次元へと引き上げてほしい。

タイトルとURLをコピーしました