AutoCAD VBAの限界を超えろ:堅牢な「バッチ処理エンジン」を構築する極意
AutoCAD VBAで「数百枚の図面を一括処理したい」と考えたとき、多くのエンジニアは安易に`Documents.Open`を連発するループを書き、そして必ず地獄を見る。「メモリリーク」「ダイアログによる停止」「予期せぬエラーでの全滅」。
これらはAutoCAD VBAの宿命ではない。設計思想の欠如が生む、ただの技術的負債だ。今日は、業務自動化の最前線で戦う諸君に、止まらない・壊れない「バッチ処理アーキテクチャ」の神髄を伝授する。
—
1. なぜ「単純なループ」でバッチ処理を組んではいけないのか
AutoCADのCOM APIは強力だが、デリケートだ。特にファイルを開く処理は、以下の罠が潜んでいる。
- モーダルダイアログの呪い: `Open`メソッド実行時に「読み取り専用」や「外部参照未解決」のダイアログが出た瞬間、プログラムはフリーズし、ユーザーの介入を待つことになる。
- メモリの断片化: 大量の図面を開閉し続けると、COMオブジェクトの参照が適切に解放されず、AutoCADの動作が徐々に重くなる。
- エラーの伝播: 1つの図面でエラーが発生した際、その処理をキャッチして次のファイルにスキップさせる設計がなければ、全プロセスが停止する。
—
2. 堅牢なバッチ処理を支える3つの設計指針
A. 異常系を前提とした「盾」を置く
処理開始時に`Application.DisplayAlerts = False`を徹底せよ。また、必ずエラーハンドリングを関数単位で独立させること。
B. オブジェクトの「所有権」を明確にする
`ThisDrawing`に依存してはならない。開いたドキュメントを明示的に変数(`AcadDocument`)に格納し、処理後は必ず`Close`メソッドでメモリを解放する。
C. 実行環境の制御
処理中は`SysVar`(システム変数)を変更するだろう。`OSNAP`や`PICKFIRST`をOFFにすることは高速化の鉄則だが、異常終了時にも必ず元に戻す(Try-Finally構文に近い考え方)ことがプロの責務だ。
—
3. 実践:プロダクションコードのテンプレート
以下は、安全かつ保守性を高めたバッチ処理の基幹コードだ。これをベースに、`ProcessDrawing`の中身を差し替えてほしい。
Option Explicit
‘ メイン処理:フォルダ内の全DWGに対して一括処理を行う
Public Sub BatchProcessDrawings()
Dim fso As Object: Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folderPath As String: folderPath = “C:\Projects\TargetDrawings\”
Dim folder As Object: Set folder = fso.GetFolder(folderPath)
Dim file As Object
‘ AutoCADの警告を抑制
Application.DisplayAlerts = False
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Path)) = “dwg” Then
Debug.Print “Processing: ” & file.Name
Call OpenAndProcess(file.Path)
End If
Next
Application.DisplayAlerts = True
MsgBox “全処理完了”, vbInformation
End Sub
‘ ドキュメント制御のラッパー
Private Sub OpenAndProcess(ByVal filePath As String)
Dim doc As AcadDocument
On Error GoTo ErrorHandler
‘ ファイルを開く(読み取り専用で開くのがバッチの基本)
Set doc = Application.Documents.Open(filePath, True)
‘ ここに具体的な処理を記述
Call ProcessDrawing(doc)
‘ 保存して閉じる(必要に応じて)
doc.Close True
Exit Sub
ErrorHandler:
Debug.Print “Error in ” & filePath & “: ” & Err.Description
If Not doc Is Nothing Then doc.Close False
End Sub
‘ 実際の図面操作ロジック
Private Sub ProcessDrawing(ByVal doc As AcadDocument)
‘ 例:特定のレイヤー名を変更する等の処理
‘ doc.Layers.Item(“OldName”).Name = “NewName”
‘ 注意:ここで doc.Regen 等を適宜呼ぶこと
doc.Regen acActiveViewport
End Sub
—
4. プロの現場での注意点:データベース連携
もし処理の過程でExcelやSQL Serverと連携する場合、「AutoCAD内のオブジェクト」と「外部データ」の同期ズレに注意せよ。
- 遅延バインディングの活用: Excel連携などで参照設定の依存関係が壊れるのを防ぐため、`CreateObject`による遅延バインディングを推奨する。
- ログ出力の徹底: どの図面が成功し、どれが失敗したかを必ずテキストファイルやCSVに残せ。数千枚規模の処理で「何が起きたか」を追えないのは、エンジニアの怠慢である。
最後に:なぜVBAなのか
AutoCADの世界では.NET (ObjectARX) への移行が叫ばれて久しい。しかし、VBAの「軽さ」と「即時性」は、小回りの利くツール開発において依然として最強の武器だ。
今回紹介したコードは、あくまで「骨格」だ。ここに、君たちが抱えている現場の課題(例:特定の属性ブロックの値のみを抽出する、特定の画層をオフにする)という「肉」を付ければ、それはもう単なるマクロではなく、立派な業務自動化エンジンとなる。
技術を使いこなせ。AutoCADを君の奴隷にするのは、APIの深淵を理解した者だけだ。
