【実務・中級編】AutoCAD図面を開かずに情報を取得!AcadApplicationの活用で図面管理を効率化 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見
第1回:図面を開かずに情報を奪取せよ!AcadApplicationがもたらす極限の図面管理術

開発プロジェクトのリーダーである私から、現場で戦うエンジニアのあなたへ問う。
「100ファイルの図面から特定のレイアウト名や属性情報を取得するためだけに、100回AutoCADのGUIを立ち上げ、図面を開き、閉じていないか?」

もし、その非効率なマクロに頼っているなら、今すぐその手を止めてほしい。GUIの描画処理、イベントハンドラ、メモリのロード・アンロード――これらはCPUとエンジニアの貴重な時間をドブに捨てる行為に他ならない。

真のプロフェッショナルは、「図面を開かずに(ドキュメントコレクションの裏側で)必要な情報を精確に抜き取る」。今回は、`AcadApplication`の真価を解き放ち、大量の図面管理業務を秒速で終わらせるための堅牢なアーキテクチャを伝授する。

1. なぜ「図面を開くアプローチ」は悪なのか?

初学者や場当たり的なコードを書くプログラマは、決まってこう書く。

‘ 【アンチパターン】絶対にやってはいけない実装
Dim doc As AcadDocument
Set doc = Documents.Open(“C:\Data\Drawing1.dwg”)
‘ 何らかの処理
doc.Close False

このコードの何が問題か?
1. 圧倒的なオーバーヘッド: AutoCADのGUIが図面を読み込み、グラフィックを構築するまでに膨大なCPUリソースと時間を消費する。
2. クラッシュリスクの増大: 開閉を繰り返す中でメモリリークを引き起こし、長時間のバッチ処理の途中でAutoCADごと沈没する。
3. 視覚的なノイズ: 画面が勝手にパチパチと切り替わり、他の作業が阻害される。

我々が目指すべきは、「不可視(Headless)領域でのオブジェクト操作」だ。AutoCADのプロセスを背後(バックグラウンド)で完全にコントロールし、必要最小限のメモリ消費でデータだけを吸い上げる。これがプロの設計思想である。

2. 堅牢な図面情報抽出エンジンの設計思想

今回構築するプロダクションコードは、単に動くだけのスクリプトではない。実務の現場で耐えうる以下の要件を満たしている。

  • エラーハンドリングの徹底: 破損した図面やパス違いでスクリプト全体が停止しない。
  • COMオブジェクトの完全解放: リソースリークを防ぐため、参照したオブジェクトは確実にメモリからパージする。
  • スケーラビリティ: 指定フォルダ内の全DWGを再帰的、あるいは一括で高速スキャンできる。

3. 【実戦投入コード】図面を開かずにレイアウトと属性を収穫する

以下のコードは、指定したフォルダ内のすべてのDWGファイルを対象に、図面を画面上に一切表示せず、レイアウト名と特定のカスタムプロパティをイミディエイトウィンドウに出力するプロフェッショナル・ツールだ。

ExcelのVBAエディタ、または独立したVBAプロジェクトから実行することを想定している(※AutoCADの参照設定が必要)。

Option Explicit

‘ =================================================================================
‘ módulo名: modDrawingAnalyzer
‘ 概要 : 図面をGUI表示せずにDWGファイルのメタデータを高速抽出するモジュール
‘ 著者 : チーフアーキテクト
‘ =================================================================================

Public Sub ExtractDrawingDataBatch()
Dim targetFolder As String
targetFolder = “C:\MyAutoCADFiles\” ‘ 監視対象フォルダを指定

If Dir(targetFolder, vbDirectory) = “” Then
MsgBox “指定されたフォルダが存在しません: ” & targetFolder, vbCritical, “パスエラー”
Exit Sub
End If

Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object
Set folder = fso.GetFolder(targetFolder)
Dim file As Object

Dim acadApp As Object
Dim isAppCreated As New Boolean

‘ 1. AutoCADアプリケーションインスタンスの取得(起動していなければ新規起動)
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application”)
If acadApp Is Nothing Then
Set acadApp = CreateObject(“AutoCAD.Application”)
isAppCreated = True
End If
On Error GoTo 0

If acadApp is Nothing Then
MsgBox “AutoCADの起動に失敗しました。”, vbCritical
Exit Sub
End If

‘ バックグラウンド実行のため非表示を維持(※バージョンにより挙動が異なる場合があります)
‘ acadApp.Visible = False ‘ ※AutoCADの仕様上、完全に消せない場合もあるが背後で処理させる

Debug.Print “=== 図面情報抽出処理を開始します ===”

Dim targetFileCount As Long
targetFileCount = 0

‘ 2. フォルダ内のDWGファイルをループ
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “dwg” Then
targetFileCount = targetFileCount + 1
Call AnalyzeSingleDrawing(acadApp, file.Path)
End If
Next file

Debug.Print “=== 処理完了 (総処理ファイル数: ” & targetFileCount & ” ) ===”

‘ 3. クリーンアップ
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
Set acadApp = Nothing
End Sub

Private Sub AnalyzeSingleDrawing(ByVal acadApp As Object, ByVal dwgPath As String)
Dim targetDoc As Object

On Error GoTo ErrorHandler

‘ 【核心】VisibleをFalseにしたまま、ドキュメントコレクションの裏側で開く
‘ Documents.Openの引数: FileName, [ReadOnly], [Password]
Set targetDoc = acadApp.Documents.Open(dwgPath, True)

Debug.Print “—————————————-”
Debug.Print “ファイル名: ” & targetDoc.Name

‘ A. レイアウト名の取得
Dim layout As Object
Debug.Print ” [レイアウト一覧]”
For Each layout In targetDoc.Layouts
Debug.Print ” – ” & layout.Name
Next layout

‘ B. 特定のブロック参照や属性の存在確認(例としてモデル空間のエンティティ数をカウント)
Dim entityCount As Long
entityCount = targetDoc.ModelSpace.Count
Debug.Print ” [モデル空間エンティティ数]: ” & entityCount & “件”

‘ 処理が終わったら変更を保存せずに閉じる (SaveChanges = False)
targetDoc.Close False
Set targetDoc = Nothing
Exit Sub

ErrorHandler:
‘ 破損ファイルやパスワード保護ファイルでスクリプトが止まらないための防壁
Debug.Print ” 【エラー発生】ファイル解析に失敗しました: ” & dwgPath & ” (理由: ” & Err.Description & “)”
If Not targetDoc Is Nothing Then
targetDoc.Close False
Set targetDoc = Nothing
End Error
Resume Next
End Sub

4. コードの急所:エンジニアが押おくべき3つのポイント

① `Documents.Open(path, True)` による読取専用・バックグラウンドロード

第2引数に `True`(ReadOnly)を指定している点に注目してほしい。これにより、図面がロックされるのを防ぎ、ネットワーク上の共有図面であっても他の作業者の邪魔をせずに情報を吸い出せる。また、書き込み権限を要求しないため、オープン処理そのものが高速化する。

② 徹底的なオブジェクトの解放(Garbage Collectionの意識)

VBAのCOM操作において、`Set obj = Nothing` を怠ることは「メモリリークを放置するテロ行為」と同義だ。特にループ内で次々とドキュメントを開閉するアーキテクチャでは、参照を確実に切り離さないと、処理後半でメモリ不足エラー(Automation Error)を引き起こす。例外発生時(ErrorHandler)も含め、確実に `Nothing` を代入する防衛的プログラミングを徹底せよ。

③ 堅牢なエラーハンドリング(`On Error Resume Next` の正しい使い方)

「エラーを全て無視する悪質なコード」ではなく、「特定の腐ったファイルによってバッチ全体が停止するのを防ぐための外科的措置」としてエラーハンドリングを配置している。ログ(イミディエイトウィンドウ)にエラー内容を残しつつ、次のファイルへ強制的に処理を移行させる設計が、夜間バッチを成功させる秘訣だ。

5. さらなる高みへ:データベース(Excel/SQLite)連携のすゝめ

上記のコードでは `Debug.Print` でコンソールに出力しているだけだが、実務ではここからExcelワークシートへの書き込みや、SQLiteなどの軽量DBへのバルクインサートへ拡張することになる。

例えば、取得したレイアウト名やエンティティ数を構造体(あるいはカスタムクラス)に格納し、ADO(ActiveX Data Objects)を経由してデータベースへ蓄積すれば、社内の「図面アセット検索ポータル」のバックエンドエンジンが完成する。

総括

図面を開かずに情報を制する者は、AutoCAD VBAを制する。
GUIの呪縛から解放されたあなたのアプリケーションは、数分、数時間かかっていた図面監査・情報抽出のタスクを、文字通り「秒単位」へと昇華させるはずだ。

現場のボトルネックを技術で叩き潰せ。健闘を祈る。

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