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

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

【上級プロフェッショナル向け】ObjectDBXを用いた「超高速」属性検索:1000枚の図面を開かずに特定文字列を抽出・保存する極意

大量の図面データから特定の属性情報(図面番号、プロジェクト名、設計者など)を抽出する業務。多くの開発者は、まずこう考えます。
「`Documents.Open` で図面を一つずつ開き、中身を読み取って、保存して閉じる」

もし君がそう考えているなら、今すぐその設計を捨てなさい。

1,000枚の図面をUI経由で開いていたら、メモリは枯渇し、AutoCADはフリーズし、作業が終わる頃にはコーヒーが冷め切っている。プロフェッショナルが求めるのは「結果」であり、「プロセス(画面の動き)」ではない。

本稿では、AutoCADの内部データベースに直接アクセスするObjectDBX技術を駆使し、UIのオーバーヘッドを完全に排除した「超高速・低負荷」な一括処理エンジンの設計思想と、実戦投入可能なプロダクションコードを伝授する。

1. なぜ `Documents.Open` では「勝てない」のか

業務自動化の設計において、最も重要なのは「リソースのライフサイクル」を理解することだ。

従来の `Documents.Open` の致命的な欠陥

1. UI描画のオーバーヘッド: 図面を開くたびに、AutoCADはグラフィックスエンジンを起動し、ビューポートを構築し、リボンやツールバーを再描画する。これは「データが欲しいだけ」の処理においては、膨大な無駄だ。
2. メモリ消費の爆発: `Documents` コレクションに図面が追加されるたびに、メモリ消費量は指数関数的に増大する。
3. ユーザー・インターフェースの拘束: 処理中にユーザーが図面を操作できず、自動化ツールが「作業を邪魔する存在」になってしまう。

ObjectDBXという「裏口」

ObjectDBXは、AutoCADのグラフィックスエンジンを介さず、DWGのデータベース構造に直接コネクトする「ヘッドレス(画面なし)」なインターフェースだ。
図面を「描画対象」としてではなく、「単なるデータファイル」として扱う。これにより、処理速度は従来の10倍〜100倍に達し、メモリ消費も極限まで抑えられる。

2. 堅牢な設計のための「3つの鉄則」

ObjectDBXは強力だが、一筋縄ではいかない。設計段階で以下の3点を考慮しなければ、ツールはすぐにクラッシュする。

① バージョン互換性の壁

ObjectDBXは、AutoCADのバージョンに依存する。AutoCAD 2024を使っているなら、`ObjectDBX.AxDbDocument.24` のように、適切なバージョンを指定してオブジェクトを生成しなければならない。これを怠ると、新しい形式のDWGを読み込んだ瞬間にエラーで死ぬ。

② エラーハンドリングの徹底(「死なせない」設計)

大量のファイルを回す際、必ず「破損したDWG」や「読み取り専用ファイル」に遭遇する。一つのファイルのエラーでループ全体を止めるのは、素人の仕事だ。「エラーを検知し、ログに記録して、次のファイルへ進む」。これがプロの設計だ。

③ メモリ解放の儀式

COMオブジェクトは、明示的に `Set obj = Nothing` を行わなければ、メモリ上に幽霊のように残り続ける。1,000枚のループの中でこれを怠れば、メモリリークによりシステム全体が不安定になる。

3. プロダクション・コード:高速属性抽出エンジン

以下に、指定したフォルダ内の全DWGファイルを走査し、ブロック属性(Attribute)から特定の情報を抽出する、実戦的なVBAコードを示す。

' ==============================================================================
' Module: RapidAttributeExtractor
' Description: ObjectDBXを用いた高速図面スキャンエンジン
' Author: Chief Architect
' ==============================================================================

Option Explicit

' 抽出結果を格納するための構造体(クラスモジュールに分けるのが理想的だが、ここでは簡略化)
' 本来はクラスモジュールを作成し、Propertyとして定義すべき。

Sub ExecuteMassiveScan()
    Dim targetFolder As String
    Dim dbxDoc As Object
    Dim fso As Object
    Dim file As Object
    Dim dwgPath As String
    Dim targetString As String
    Dim currentVersion As Integer
    
    ' --- 設定エリア ---
    targetFolder = "C:\Project\Drawings\" ' スキャン対象フォルダ
    targetString = "PROJ-2024-"          ' 検索したいキーワードの接頭辞
    currentVersion = 24                  ' AutoCAD 2021-2024系 (バージョンに合わせて調整)
    ' ------------------

    Set fso = CreateObject("Scripting.FileSystemObject")
    
    If Not fso.FolderExists(targetFolder) Then
        MsgBox "対象フォルダが存在しません。", vbCritical
        Exit Sub
    End If

    ' ObjectDBXの初期化 (Late Bindingによる柔軟な生成)
    On Error Resume Next
    Set dbxDoc = CreateObject("ObjectDBX.AxDbDocument." & currentVersion)
    If dbxDoc Is Nothing Then
        MsgBox "ObjectDBXの初期化に失敗しました。バージョン指定を確認してください。", vbCritical
        Exit Sub
    End If
    On Error GoTo ErrorHandler

    Debug.Print "--- Scan Started: " & Now & " ---"

    ' フォルダ内のファイルをループ
    For Each file In fso.GetFolder(targetFolder).Files
        If LCase(fso.GetExtensionName(file.Path)) = "dwg" Then
            dwgPath = file.Path
            
            ' 個別ファイル処理の実行
            ProcessSingleDWG dbxDoc, dwgPath, targetString
        End If
    Next file

    Debug.Print "--- Scan Completed: " & Now & " ---"
    MsgBox "スキャンが完了しました。詳細はイミディエイトウィンドウを確認してください。", vbInformation

CleanUp:
    Set dbxDoc = Nothing
    Set fso = Nothing
    Exit Sub

ErrorHandler:
    Debug.Print "CRITICAL ERROR: " & Err.Description
    Resume CleanUp
End Sub

''' <summary>
''' 個別のDWGファイルに対して属性検索を行う
''' </summary>
Private Sub ProcessSingleDWG(ByRef dbxDoc As Object, ByVal filePath As String, ByVal searchKey As String)
    Dim ent As Object
    Dim blockRef As Object
    Dim attRef As Object
    Dim foundMatch As Boolean
    
    On Error GoTo FileError
    
    ' 図面をメモリにロード (UIは介さない)
    dbxDoc.Open filePath
    foundMatch = False
    
    ' ModelSpace内のエンティティを走査
    ' ※ObjectDBXでは、ModelSpaceやPaperSpaceへ直接アクセス可能
    For Each ent In dbxDoc.ModelSpace
        
        ' ブロック参照(Insert)を探す
        If ent.EntityName = "AcDbBlockReference" Then
            Set blockRef = ent
            
            ' ブロックが属性を持っているか確認
            If blockRef.HasAttributes Then
                ' 属性のループ
                For Each attRef In blockRef.GetAttributes
                    ' 条件判定: 属性値に特定の文字列が含まれているか
                    If InStr(1, attRef.TextString, searchKey, vbTextCompare) > 0 Then
                        ' ヒットした場合の処理(ここではイミディエイトウィンドウへ出力)
                        ' 実務では、ここでCSV出力やSQLへのInsertを行う
                        Debug.Print "[MATCH] File: " & filePath & " | Tag: " & attRef.TagString & " | Value: " & attRef.TextString
                        foundMatch = True
                        Exit For ' 1つのブロック内で見つかれば次へ
                    End If
                Next attRef
            End If
        End If
        
        If foundMatch Then Exit For ' ファイル内で見つかればその図面の走査を終了
    Next ent

    If Not foundMatch Then
        ' Debug.Print "[SKIP] " & filePath
    End If

    Exit Sub

FileError:
    ' ファイルが破損している、またはロックされている場合のハンドリング
    Debug.Print "[ERROR] Failed to process: " & filePath & " | Reason: " & Err.Description
    Resume Next
End Sub

4. アーキテクトの視点:さらなる高みへ

このコードは「動く」レベルだが、プロフェッショナルな製品にするには、以下の拡張が必要だ。

データベース連携の設計

`Debug.Print` で済ませるのは、あくまでデバッグ段階だ。実務では、抽出したデータを SQLite や SQL Server に直接書き込む設計にすべきだ。

  • NG: ループの中で毎回ファイルを開いて書き込む。
  • OK: メモリ上の `Collection` や `Array` に一旦すべて格納し、ループ終了後に一括で `Bulk Insert` する。I/O(入出力)の回数を減らすことが、速度への最短距離だ。

並列処理の検討(Advanced)

VBA単体ではマルチスレッドは扱いにくい。もし数万枚規模のデータを扱うなら、AutoCADを複数インスタンス立ち上げる、あるいはPythonの `ezdxf` ライブラリなどを用いて、AutoCADのエンジンに頼らずに解析するハイブリッド構成を検討しなさい。

メモリ管理の極意

`dbxDoc.Open` を繰り返す際、稀に内部的な参照が残り、メモリが解放されないことがある。非常に大規模な処理を行う場合は、一定件数(例:100ファイル)ごとに `Set dbxDoc = Nothing` を行い、オブジェクトを再生成する「リフレッシュ戦略」を取り入れなさい。

結論

ObjectDBXは、AutoCAD自動化における「魔法の杖」ではない。しかし、正しく扱えば、君のツールを「ただの便利スクリプト」から「企業の基幹インフラを支えるエンジニアリングツール」へと昇華させる。

「画面を見せるな、データを見せろ。」

これが、真の自動化エンジニアが持つべきマインドセットだ。

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