【入門編】【上級プロフェッショナル向け】大量図面の一括変換における「メモリリーク」対策:一定数処理ごとのAcadApplication再起動とセッション復元 – AutoCAD VBA解析バイブル

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

AutoCAD VBAの深淵へようこそ:数千枚の図面を制する「セッション・リフレッシュ」の極意

こんにちは。技術の荒波を共に乗り越えていく、あなたの先輩エンジニアです。

「マクロの記録」から一歩踏み出し、自分でコードを書き始めたあなた。素晴らしい一歩です!「図面を自動で開いて、名前を変えて、保存して閉じる」……そんな単純なループ処理が書けるようになると、魔法を手に入れたような気分になりますよね。

しかし、プロフェッショナルの現場では、その魔法が時に「呪い」に変わることがあります。

数千枚、あるいは数万枚という膨大な図面を連続して処理しようとしたとき、あなたのPCのメモリ(RAM)が、まるで底の抜けたバケツのようにどんどん消費され、最終的にAutoCADが沈黙してしまう……。そんな経験はありませんか?

今日は、初級者が必ずぶつかる「メモリ枯渇(メモリリーク)問題」を突破し、プロレベルの「堅牢なバッチ処理システム」を構築するための、設計思想と実装テクニックを伝授します。

ここをクリアすれば、あなたのVBAは「ただ動くコード」から「現場で信頼されるシステム」へと進化しますよ。

1. なぜ「Close」しているのにメモリが足りなくなるのか?

まず、敵の正体を知ることから始めましょう。

通常、コードの中で `ThisDrawing.Close` を実行すれば、図面は閉じられ、メモリも解放される……そう思いますよね? 実は、AutoCADのような巨大なアプリケーション(COMオブジェクト)の世界では、そう単純ではないのです。

メモリリークの正体

AutoCADは、図面を閉じた後も、以下のような「目に見えないゴミ」をメモリ内に残してしまうことがあります。

  • Undo(元に戻す)情報の残骸: 履歴を保持するためのキャッシュ。
  • COMオブジェクトの参照残り: VBA側で変数に代入したオブジェクトが、メモリ上で「まだ使われている」と判定されて解放されない現象。
  • アプリケーション内部の断片化: 長時間起動し続けることで、メモリの配置がバラバラになり、大きな図面を開くための「連続した空き領域」が確保できなくなる現象。

これらが積み重なると、たとえ図面を1枚ずつ丁寧に閉じていても、AutoCAD自体の消費メモリは右肩上がりに増えていきます。これがメモリリークです。

2. プロの設計思想: 「コントローラー」と「ワーカー」の分離

ここで、凡庸なエンジニアとプロフェッショナルの分かれ道があります。

凡庸なエンジニアは、AutoCADの中で動くVBAだけで何とかしようとします。しかし、自分自身(AutoCAD)を終了させてリフレッシュすることは、自分自身を消滅させることなので、VBA単体では不可能なのです。

プロフェッショナルは、役割を2つに分けます。

1. コントローラー(司令塔): AutoCADの起動・終了、および「次にどの図面を処理すべきか」を管理する。
2. ワーカー(作業員): AutoCADの中で起動し、渡された図面を処理して、終わったら「完了」を報告して消える。

この「外側から内側を制御する」という考え方が、大量処理における鉄則です。

処理の全体像(アーキテクチャ図)

[ コントローラー (VBScript or Excel VBA) ]
|-- 1. AutoCADを起動 (Worker) |-- 2. 図面リストから「未処理」を取得 |-- 3. 指定枚数(例: 50枚)を処理させる |-- 4. AutoCADを強制終了 (Memory Refresh!) |-- 5. 処理済みリストを更新 |-- 6. 1に戻る(まだ未処理があれば)

3. 実装: 堅牢なバッチ処理システムの構築

今回は、最も導入しやすい「VBScriptをコントローラー、AutoCAD VBAをワーカー」にする構成を紹介します。VBScriptはWindows標準機能なので、特別な準備なしに「AutoCADを外から操る」ことができます。

【ステップ1】 ワーカー側:AutoCAD VBA

AutoCAD内で実行されるコードです。ここでは「指定されたファイルを処理する」ことに専念します。

' AutoCAD内の標準モジュールに記述
Public Sub ProcessBatch()
    On Error Resume Next ' エラーで止まらないように制御
    
    Dim filePath As String
    ' コマンドライン引数からファイルパスを受け取る仕組みは
    ' 本来は複雑なため、ここでは「特定のテキストファイルに書かれた
    ' 次の処理対象」を読み取る簡易的な方法をとります
    
    filePath = GetNextTargetFile()
    
    If filePath = "" Then
        MsgBox "処理すべき図面がありません。"
        Exit Sub
    End If

    ' --- ここからメイン処理 ---
    Dim dwgDoc As AcadDocument
    Set dwgDoc = Documents.Open(filePath)
    
    ' (例) 図面のバージョンを最新に変換して保存
    ' ここにあなたの自動化ロジックを記述します
    dwgDoc.SaveAs filePath ' 実際には新しいパスを指定
    dwgDoc.Close
    ' --- ここまで ---

    ' 処理完了をコントローラーに伝えるためのフラグ(ログ出力など)
    WriteProcessLog filePath
End Sub

' 次のファイルを取得する補助関数
Private Function GetNextTargetFile() As String
    ' 実装例:処理待ちリスト(txt)から一行読み込むロジック
    ' (詳細は省略しますが、リスト管理が重要です)
End Function

' ログを書き出す補助関数
Private Sub WriteProcessLog(path As String)
    ' 処理済みリストに書き込むロジック
End Sub

【ステップ2】 コントローラー側:VBScript (.vbs)

これが「司令塔」です。メモ帳に貼り付けて `.vbs` という拡張子で保存してください。

' Controller.vbs
Option Explicit

Dim objExcel, objAutoCAD, shell, fso
Set fso = CreateObject("Scripting.FileSystemObject")
Set shell = CreateObject("WScript.Shell")

' 設定項目
Dim BATCH_SIZE, TARGET_DIR
BATCH_SIZE = 50 ' 50枚ごとにAutoCADを再起動してメモリをリフレッシュ
TARGET_DIR = "C:\DrawingData\Work\" ' 図面があるフォルダ

' メインループ
Do While True
    ' 1. 未処理の図面がまだあるか確認
    Dim remainingFiles
    remainingFiles = CountUnprocessedFiles(TARGET_DIR)
    
    If remainingFiles = 0 Then Exit Do ' 全て終わったら終了

    ' 2. AutoCADを起動してワーカーを実行
    MsgBox BATCH_SIZE & "枚の処理を開始します。AutoCADを起動します。"
    
    ' AutoCADを起動し、VBAマクロを実行するコマンドライン
    ' /c はコマンド実行、/b はスクリプト実行などを指します
    ' ここでは「AutoCADを起動して、特定のスクリプトを実行する」命令を送ります
    Dim acadPath, command
    acadPath = """C:\Program Files\Autodesk\AutoCAD 20xx\acad.exe"""
    ' スクリプト(SCR)経由でVBAを叩くのが最も確実です
    command = acadPath & " /b ""C:\Scripts\BatchRunner.scr"""
    
    shell.Run command, 1, True ' AutoCADが終了するまで待機
    
    ' 3. AutoCADが終了した=メモリがリフレッシュされた!
    ' 次のバッチへ進む
Loop

MsgBox "全ての処理が完了しました!お疲れ様でした。"

' --- 以下、補助関数(ファイルカウント等)を実装 ---
Function CountUnprocessedFiles(dirPath)
    ' 処理待ちリストの行数を数えるロジック
    CountUnprocessedFiles = 100 ' 仮の数値
End Function

4. 陥りやすいエラーと「プロの対策」

このシステムを運用する上で、あなたが直面するであろう壁とその回避術を教えておきます。

① 「AutoCADが閉じない!」問題

`shell.Run` で実行した際、AutoCADがエラーダイアログを出して止まっていると、コントローラーは「AutoCADが終了する」のを永遠に待ち続けてしまいます(フリーズ状態)。

  • 対策: AutoCAD側のVBAに必ず `On Error Resume Next` を入れ、エラーが起きても必ず `ThisDrawing.Close` を通って終了するように設計してください。また、`On Error GoTo ErrorHandler` を使い、エラー内容をテキストファイルに書き出すようにしておくと、後で「なぜあの図面で止まったのか」が分かります。

② 「ファイルがロックされている」問題

AutoCADが異常終了した際、図面ファイルが「読み取り専用」としてロックされたまま残ることがあります。

  • 対策: コントローラー側で、次に処理を開始する前に `fso.GetFile(path).Attributes` をチェックし、ロックされていないか確認するロジックを入れると極めて堅牢になります。

③ 「セッション復元」の考え方

大量処理の途中でPCが再起動したり、停電したりすることもあります。

  • 対策: 「どのファイルまで終わったか」を常に外部ファイル(CSVやテキスト)に書き出し続けてください。「一括ですべてやる」のではなく、「いつでも途中から再開できる」設計こそが、真のプロフェッショナルの仕事です。

最後に:一歩先へ進むあなたへ

いかがでしたか?
「AutoCADの中でコードを書く」という視点から、「AutoCADというプロセスを外から管理する」という視点への転換。これが、業務自動化エンジニアとしての大きな成長の分岐点です。

最初は複雑に感じるかもしれません。でも、この「コントローラー・ワーカー方式」を一度マスターしてしまえば、AutoCADだけでなく、Excel、CAD、その他あらゆるソフトウェアの大量処理に応用が効くようになります。

一歩ずつ、着実に。
コードの向こう側にある「確実な動作」を目指して、楽しんで書き進めてください。応援していますよ!

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