【テクニカル・上級編】【上級プロフェッショナル向け】ObjectDBXを用いた「超高速」属性検索:1000枚の図面を開かずに特定文字列を抽出・保存 – AutoCAD VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の自動化】ObjectDBXによる非表示型・超高速DWGデータ・マイニング:1000枚の図面を「開かずに」支配する

図面管理の自動化を志すエンジニアが、最初に直面する「壁」がある。それは、大量のDWGファイルを走査する際に発生する、致命的なパフォーマンスの低下とメモリの枯渇だ。

多くの者は、`Documents.Open` メソッドを使い、AutoCADのUIを介して一つずつ図面を開いていく。しかし、それは「エンジニア」の仕事ではない。それは単なる「操作の自動化」に過ぎない。AutoCADのグラフィックスエンジン、LISPのロード、ダイアログの制御、そして膨大なUIのオーバーヘッド……それらをすべて引き受けて、数千枚の図面を処理しようとするのは、戦車で蟻の巣を掘り進めるような愚行である。

真のアーキテクトが選ぶ道は、ObjectDBXだ。

本稿では、AutoCADのGUI(グラフィックスエンジン)を完全にバイパスし、メモリ上のデータ構造に直接アクセスすることで、数千枚の図面から属性情報をミリ秒単位で抽出する「超高速データマイニング」の極意を伝授する。

1. ObjectDBXの本質:なぜ「開かない」ことが重要なのか

通常の `Document` オブジェクトは、ユーザーが画面上で図面を見るための「重厚な外装」を備えている。一方、`ObjectDBX` は、DWGのデータベース構造(Entity, Layer, Block, Attribute等)に直接アクセスするための「軽量なインターフェース」である。

ObjectDBXを採用すべき技術的根拠

  • UIオーバーヘッドの排除: 画面描画、カーソル更新、コマンドラインの出力を一切行わない。
  • メモリ効率の極大化: 図面全体をグラフィックスメモリに展開せず、純粋なデータ構造のみをメモリにロードする。
  • 非同期的な処理への適性: AutoCADのメインスレッドを占有しにくいため、バッチ処理のスケジューリングが容易になる。

ただし、注意せよ。ObjectDBXは「図面を見る」ためのものではない。あくまで「データを操作する」ためのものだ。LISPの実行や、画面表示を伴うコマンドの実行は不可能である。この制約を理解して初めて、真の使い分けが可能となる。

2. 実装の核心:堅牢なデータ抽出エンジン

以下に、指定したフォルダ内の全てのDWGファイルから、特定の「属性(Attribute)」を検索し、その結果を抽出するプロフェッショナル向けのコード構造を示す。ここでは、メモリリークを防ぐための「明示的なオブジェクト解放」と、エラー発生時にプロセスを止めない「例外処理」に焦点を当てる。

' ==============================================================================
' Module: Module_DBX_Miner
' Description: ObjectDBXを用いた超高速DWG属性検索エンジン
' Author: Chief Architect
' ==============================================================================

Option Explicit

' AutoCADのバージョンに応じたObjectDBXのプログラマブルID
' 例: AutoCAD 2021 = "ObjectDBX.AxDbDocument.24"
'     AutoCAD 2024 = "ObjectDBX.AxDbDocument.25"
Private Const DBX_VERSION As String = "ObjectDBX.AxDbDocument.24"

Sub MassAttributeSearch()
    Dim targetFolder As String
    Dim fileName As String
    Dim dbxDoc As Object ' ObjectDBX.AxDbDocument
    Dim acadApp As Object
    Dim searchString As String
    Dim resultCount As Long
    
    ' --- 初期設定 ---
    targetFolder = "C:\Data\Project_Drawings\" ' 対象ディレクトリ
    searchString = "PROJECT_ID"               ' 検索対象の属性タグ名
    resultCount = 0
    
    On Error Resume Next
    Set acadApp = GetObject(, "AutoCAD.Application")
    If acadApp Is Nothing Then
        MsgBox "AutoCADが起動していません。", vbCritical
        Exit Sub
    End If
    On Error GoTo ErrorHandler

    ' フォルダ内のDWGファイルを走査
    fileName = Dir(targetFolder & "*.dwg")
    
    Do While fileName <> ""
        Debug.Print "Processing: " & fileName
        
        ' --- ObjectDBX インスタンスの生成 ---
        ' ループ内で毎回生成することで、メモリの断片化を抑制する
        Set dbxDoc = acadApp.GetInterfaceObject(DBX_VERSION)
        
        If Not dbxDoc Is Nothing Then
            On Error Resume Next
            ' 図面をメモリ上にオープン(UIは介さない)
            dbxDoc.Open (targetFolder & fileName)
            
            If Err.Number = 0 Then
                ' 属性検索の実行
                resultCount = resultCount + ExtractAttributeValue(dbxDoc, searchString)
            Else
                Debug.Print "Error opening " & fileName & ": " & Err.Description
            End If
            On Error GoTo ErrorHandler
            
            ' --- 極めて重要なステップ: 明示的なメモリ解放 ---
            ' ObjectDBXはCOMオブジェクトであるため、Nothingを代入するだけでは
            ' 不十分な場合がある。スコープを抜ける前に確実に解放せよ。
            dbxDoc.Close
            Set dbxDoc = Nothing
        End If
        
        fileName = Dir() ' 次のファイルへ
    Loop

    MsgBox "完了。抽出されたレコード数: " & resultCount, vbInformation
    Exit Sub

ErrorHandler:
    MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
    Set dbxDoc = Nothing
End Sub

''' <summary>
''' 図面内の全てのブロック参照を走査し、指定されたタグの属性値を返す
''' </summary>
Private Function ExtractAttributeValue(ByRef dbxDoc As Object, ByVal tagToFind As String) As Long
    Dim ent As Object
    Dim blockRef As Object
    Dim attRef As Object
    Dim count As Long
    
    count = 0
    
    ' 図面内の全エンティティを走査
    ' Note: 大規模図面では、モデル空間のみを対象とするのが効率的
    For Each ent In dbxDoc.ModelSpace
        ' ブロック参照(AcDbBlockReference)を特定
        If ent.ObjectName = "AcDbBlockReference" Then
            Set blockRef = ent
            
            ' 属性が存在するか確認
            If blockRef.HasAttributes Then
                For Each attRef In blockRef.GetAttributes
                    ' ターゲットのタグ名と一致するか
                    If UCase(attRef.TagString) = UCase(tagToFind) Then
                        ' ここで結果をログ出力、あるいは外部DB/CSVへ書き出す
                        Debug.Print "Found: " & attRef.TextString
                        count = count + 1
                    End If
                Next attRef
            End If
        End If
    Next ent
    
    ExtractAttributeValue = count
End Function

3. アーキテクトの知見:パフォーマンスを極限まで引き出す3つの鉄則

コードを書くだけでは不十分だ。大規模システムを運用する上で、以下の「設計思想」を血肉化せよ。

① オブジェクトのライフサイクル管理(Memory Hygiene)

VBAのガベージコレクションは、C++やJavaほど強力ではない。特にObjectDBXのような外部COMオブジェクトを扱う場合、`Set obj = Nothing` を怠ると、AutoCADのメモリ使用量が指数関数的に増大し、最終的に `Out of Memory` でクラッシュする。
「使い終わったオブジェクトは、その場で殺す」。これが鉄則だ。

② エラー・アイソレーション(Error Isolation)

1000枚の図面の中には、必ず「破損したDWG」や「バージョンが異なるDWG」が含まれている。一つのエラーでバッチ処理全体を停止させるのは、素人の設計だ。
`On Error Resume Next` を局所的に使い、エラーが発生したファイルはログに記録して即座にスキップし、次のファイルへ移行する「レジリエンス(回復力)」を持たせろ。

③ バージョン互換性の抽象化

`GetInterfaceObject` に渡す文字列(`ObjectDBX.AxDbDocument.XX`)は、AutoCADのバージョンに依存する。これをハードコードするのは、保守性の観点から最悪の選択だ。
実務では、実行環境のAutoCADバージョンを `GetInterfaceObject` の引数から動的に解決するか、設定ファイルから読み込む構成にせよ。

結言

ObjectDBXを用いたアプローチは、単なる高速化のテクニックではない。それは、AutoCADという巨大なソフトウェアを「ユーザーの道具」としてではなく、「データリポジトリ」として捉え直す、エンジニアリングのパラダイムシフトである。

この技術をマスターすれば、あなたは設計業務の傍らで、社内の膨大な図面資産を自在に操る「データの支配者」となるだろう。

Keep coding, Keep optimizing.

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