【テクニカル・上級編】【実務中級】FSOとAcadApplicationの連携:特定フォルダ内の全DWGファイルに対して「名前削除(Purge)」と「監査(Audit)」を一括実行 – AutoCAD VBA解析バイブル

スポンサーリンク

【実務中級】FSOとAcadApplicationの連携:特定フォルダ内の全DWGファイルに対して「名前削除(Purge)」と「監査(Audit)」を一括実行

図面管理の現場において、肥大化したDWGファイルのクリーンアップは永遠の課題である。
未定義の画層、ゴミオブジェクト、破損したデータベースインデックス。これらが蓄積することで、AutoCADの動作は重くなり、最悪の場合は致命的な図面破損を引き起こす。

手動で数千枚の図面を開き、`PURGE` と `AUDIT` を実行して上書き保存する――そんな非効率な作業にエンジニアの貴重な時間を割くべきではない。

今回は、`FileSystemObject (FSO)` と `AcadApplication` オブジェクトを極限までチューニングし、バックグラウンドで安全かつ高速に一括処理を行うバッチ処理ツールの全貌を解説する。
レガシーなVBAの作法に囚われず、メモリリークとCOMプロセスの暴走を完全に制御する「実務の知見」をここに共有する。

1. アーキテクチャ設計の核心:なぜ「バックグラウンド一括処理」は難解なのか?

AutoCAD VBAを用いたバッチ処理において、アマチュアとシニアエンジニアの決定的な違いは「オブジェクトのライフサイクル管理」「エラーハンドリングの堅牢性」にある。

単に `Documents.Open` を繰り返すだけのコードは、数ファイルを処理しただけでメモリリークを起こし、AutoCAD本体がフリーズするか、COM例外(`-2147417848 (8001010a)` 呼び出しが別のスレッドにされています)でクラッシュする。

これを防ぐための鉄則は以下の3点である。

1. 単一インスタンスの再利用と適切なクローズ: 毎回AutoCADを起動するのではなく、1つの `AcadApplication` セッション内でドキュメントを順次開き、閉じ、メモリを解放する。
2. 完全なエラーバリア: 1つの図面が完全に破損しており、`Open` メソッド自体が例外を吐いた場合でも、マクロ全体が停止せず次のファイルへ処理を移行する。
3. 視覚的ノイズの排除: `Visible = False` により画面描画やUIイベントを完全に抑制し、処理速度を極限まで高める。

2. 実装コード:一括クリーンアップ・バッチエンジン

以下のコードを、Excel VBAまたはAutoCADのVBAエディタ(`ThisDrawing` または標準モジュール)に実装する。
実務でそのまま運用できるよう、エラーハンドリングとFSOによるファイル走査を網羅している。

Option Explicit

‘ ==============================================================================
‘ 概要: 指定フォルダ内の全DWGファイルに対し、PurgeとAuditをサイレント実行する
‘ ターゲット: AutoCAD 2013 ~ 最新バージョン (COMインターフェース対応)
‘ ==============================================================================
Public Sub BatchPurgeAndAudit()
Dim fso As Object
Dim targetFolder As String
Dim acadApp As Object
Dim doc As Object
Dim fileItem As Object
Dim folderObj As Object
Dim fileCount As Long
Dim successCount As Long

‘ — 処理対象フォルダの指定(必要に応じて変更してください) —
targetFolder = “C:\Work\AutoCAD_Drawings\”

‘ FSOのインスタンス生成
Set fso = CreateObject(“Scripting.FileSystemObject”)

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

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

If acadApp Is Nothing Then
MsgBox “AutoCADの起動に失敗しました。”, vbCritical, “致命的エラー”
Exit Sub
End If

‘ バックグラウンド実行のため、ウィンドウを非表示にする
‘ ※環境によってはFalseにすると動作が不安定になる場合があるため、その場合はTrueにする
acadApp.Visible = False

Set folderObj = fso.GetFolder(targetFolder)
fileCount = 0
successCount = 0

‘ ステータスバー表示の抑制(高速化)
acadApp.Preferences.Display.TextScreenampilkan = False

‘ フォルダ内の全ファイル走査
For Each fileItem In folderObj.Files
If LCase(fso.GetExtensionName(fileItem.Name)) = “dwg” Then
fileCount = fileCount + 1

‘ 個別ファイルの処理でエラーが発生してもループを止めないためのトラップ
On Error GoTo ErrorHandler

‘ 図面を開く(Read-Onlyではなく通常オープンが必要なため、第2引数はFalse)
Set doc = acadApp.Documents.Open(fileItem.Path, False)

‘ 1. Audit(監査)の実行
‘ 引数 True は「検出されたエラーを自動修正する」
doc.AuditInfo True

‘ 2. Purge(名前削除)のループ実行
‘ AutoCADの仕様上、ネストされたブロック定義等を完全に削除するためには
‘ 削除対象がなくなるまで複数回(通常3回程度)Purgeを回す必要がある。
Dim i As Long
For i = 1 to 3
doc.PurgeAll
Next i

‘ 3. 上書き保存
doc.Save

‘ 4. ドキュメントの明示的クローズ
doc.Close False
Set doc = Nothing

successCount = successCount + 1
Debug.Print “成功: ” & fileItem.Name

GoTo NextFile

ErrorHandler:
‘ エラーログをイミディエイトウインドウに出力し、次のファイルへ
Debug.Print “【エラー】ファイル処理失敗: ” & fileItem.Name & ” | 理由: ” & Err.Description
On Error Resume Next
If Not doc Is Nothing Then
doc.Close False
Set doc = Nothing
End If
On Error GoTo 0

NextFile:
End If
Next fileItem

‘ 終了処理
acadApp.Visible = True
acadApp.Preferences.Display.TextScreenampilkan = True

‘ クリーンアップ
Set acadApp = Nothing
Set folderObj = Nothing
Set fso = Nothing

MsgBox “バッチ処理が完了しました。” & vbCrLf & _
“処理対象: ” & fileCount & ” ファイル” & vbCrLf & _
“成功件数: ” & successCount & ” ファイル”, vbInformation, “処理完了”
End Sub

3. チーフアーキテクトが解説する「コードの急所」

上記のコードには、現場で培った「不具合を未然に防ぐためのノウハウ」が凝縮されている。

① `PurgeAll` の罠と3回ループの法則

多くの初心者は `doc.PurgeAll` を1回呼んで満足する。しかし、AutoCADのデータベース構造上、ブロックAの中にブロックBがあり、ブロックBの中に不要な画層が存在する場合、1回の `PurgeAll` では最上位のブロックしか綺麗にならない。
完全な軽量化を実現するためには、ループ処理による多重パージ(通常3回)が必須である。

② `On Error` のスコープ管理

バッチ処理における最大の悪夢は、500個中499個目を処理している最中に特定の図面が破損しており、マクロ全体が「実行時エラー」でストップすることだ。
ループの内側に個別のエラーハンドラ(`ErrorHandler`)を配置し、エラーが発生した図面を `doc.Close False` で強制的に捨ててメモリを回収した上で、次のファイルへ処理をジャンプ(`GoTo NextFile`)させる構造が不可欠となる。

③ COMオブジェクトの解放(メモリリーク対策)

VBAのランタイムは参照カウント方式でメモリを管理しているが、COMオブジェクトの解放は非常に気まぐれである。
ループの各イテレーションの終わり、およびマクロの終了時には、必ず `Set doc = Nothing` および `Set acadApp = Nothing` を明示し、VBAのメモリ空間からAutoCADへのゾンビ参照を排除しなければならない。これを怠ると、バックグラウンドプロセスとして `acad.exe` がタスクマネージャーに残留し続け、PCのメモリを食い潰す原因になる。

4. さらに先へ:実運用に向けた拡張提案

このスクリプトはそのまま実務で即戦力として利用可能だが、さらに社内システムとして昇華させるためのアプローチを提示する。

  • ログのファイル出力: イミディエイトウィンドウだけでなく、`FileSystemObject` を用いて処理結果(成功・失敗・ファイルサイズの変化量)をCSVログとして出力する。
  • マルチスレッド(複数インスタンス)化: マシンに強烈なスペック(多コアCPU・大容量RAM)がある場合、フォルダを分割し、複数のExcel/VBAインスタンスから並行して別々のフォルダを叩くことで、処理時間を数分の一に短縮できる。

レガシーな技術と侮られがちなVBAであるが、WindowsのCOMアーキテクチャとAutoCADのオブジェクトモデルを正しく理解し、緻密にコードを組み上げれば、極めて強力なエンタープライズ・オートメーションツールに変貌する。
日々の定型業務にエンジニアリングの力を適用し、真に価値のある設計業務に集中できる環境を構築してほしい。

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