AutoCADバッチ処理の深淵:メモリリークを葬り、無限の図面を飼い慣らす技術
AutoCAD VBAで「数百枚の図面を一括処理したい」と考えたとき、多くのエンジニアは安易に `Documents.Open` をループさせる罠に陥る。そして、数時間後にAutoCADが沈黙する(フリーズする)現実を突きつけられるのだ。
AutoCADのオブジェクトモデルは、強力だが極めて繊細だ。「開く・処理する・閉じる」という単純なループの中に、メモリ管理の悪夢が潜んでいる。 今日は、業務自動化の最前線で私が培ってきた、堅牢かつ高速なバッチ処理のアーキテクチャを伝授しよう。
—
1. バッチ処理の聖域:なぜ「標準のループ」では死ぬのか
AutoCAD VBAにおいて、`Application.Documents` を単にループさせるだけでは、メモリは解放されない。特に `ActiveDocument` を切り替えながらの操作は、COMインターフェースの参照カウントが適切に管理されず、残骸がヒープメモリに蓄積される。
極限の知見:
バッチ処理において、メインのAutoCADインスタンスを「重いGUI操作」に使ってはいけない。可能な限り `ThisDrawing` 以外のドキュメントを制御する場合、`DocumentCollection` を監視し、処理後の明示的な `Close` 処理と、VBのガベージコレクションを強制的に意識したコーディングが必須だ。
—
2. 実践:高信頼性バッチ処理エンジン
以下のコードは、指定フォルダ内のDWGを順次開き、条件を満たす図面のみを処理して保存する、プロダクション仕様のテンプレートだ。
‘ 【高信頼性バッチ処理エンジン】
Option Explicit
Public Sub BatchProcessDrawings()
Dim fso As Object
Dim folder As Object
Dim file As Object
Dim targetFolder As String
Dim doc As AcadDocument
Set fso = CreateObject(“Scripting.FileSystemObject”)
targetFolder = “C:\AutoCAD_Projects\Source”
‘ AutoCADの描画を停止し、パフォーマンスを最大化する
ThisDrawing.Application.Visible = True
For Each file In fso.GetFolder(targetFolder).Files
If LCase(fso.GetExtensionName(file.Path)) = “dwg” Then
‘ オブジェクトの完全解放を保証するスコープ
ProcessSingleFile file.Path
End If
Next
MsgBox “バッチ処理が完了しました。”, vbInformation
End Sub
Private Sub ProcessSingleFile(filePath As String)
Dim doc As AcadDocument
On Error Resume Next
‘ ドキュメントを開く(読み取り専用で開き、競合リスクを回避)
Set doc = Application.Documents.Open(filePath, True)
If Err.Number <> 0 Then
Debug.Print “Error opening: ” & filePath
Exit Sub
End If
On Error GoTo 0
‘ — 処理実行領域 —
‘ ここにレイヤー制御や図形削除などのビジネスロジックを記述
ModifyDocument doc
‘ ——————
‘ 変更を保存して閉じる(あるいは破棄)
doc.Save
doc.Close False ‘ メモリ解放の要
‘ 明示的なオブジェクト解放
Set doc = Nothing
‘ 大規模処理時はDoEventsを挟み、システムスタックをフラッシュする
DoEvents
End Sub
Private Sub ModifyDocument(doc As AcadDocument)
‘ 処理ロジック:ここではレイヤーの有無を判定
Dim layer As AcadLayer
For Each layer In doc.Layers
If layer.Name = “OLD_TEMPLATE” Then
layer.Delete
End If
Next
End Sub
—
3. シニアが意識すべき「Windows API」と「メモリ」の境界線
コード内で `DoEvents` を呼ぶのは、単なる気休めではない。AutoCADのWindowsメッセージキューが飽和するのを防ぐための処置だ。さらに、大規模な環境(数百枚以上のバッチ)では、AutoCADを「閉じて再起動する」という禁断のテクニックが有効になる。
システム間連携の極意
もし処理が複雑でメモリ負荷が高い場合、VBA単体で完結させるな。
1. メインプロセッサ: VBScriptまたはVB.NET(スタンドアロン)から `AutoCAD.Application` を起動。
2. サブプロセッサ: 処理済みの図面ごとにAutoCADインスタンスを `Quit` させ、プロセスを完全に殺す。
これが、レガシー環境における最強のメモリクリーン戦略だ。`Process.Kill` (VB.NETの場合) や `TaskKill` コマンド(Windows API/Shell連携)を駆使し、AutoCADのゾンビプロセスを許すな。
—
4. 最後に:エンジニアへの提言
AutoCAD VBAはレガシーと言われるが、図面の「物理的な操作」においては今なお最強のインターフェースだ。ただし、それを制御する側の人間が「APIの参照カウント」と「Windowsのプロセス寿命」を理解していなければ、それはただの不安定なツールに成り下がる。
コードをコピペするだけでは、真の自動化は成し遂げられない。
「なぜここでメモリを解放する必要があるのか?」「なぜこのAPIは非同期で呼ぶべきなのか?」
その疑問を持ち続けた者だけが、AutoCADという巨大な城を自在に操る権利を得るのだ。
健闘を祈る。貴殿の現場が、自動化の恩恵で溢れることを期待している。
