【上級プロフェッショナルへの道】大量図面処理の壁を越える:GDIリソース監視と自己修復型オートメーション
こんにちは。AutoCAD VBAの世界へようこそ。
「マクロの記録」ボタンを押して、最初の一歩を踏み出したあなた。素晴らしいですね!まずは「動くものを作る」ことが何より大切です。しかし、あなたがもし「数百枚、数千枚の図面を、夜通し自動で処理させたい」と願うなら、そこには「マクロの記録」では決して教えてくれない、恐ろしい壁が立ちはだかります。
それは、「リソースの枯渇」です。
大量の図面を連続して開閉していると、いつの間にかAutoCADが重くなり、最終的には「応答なし」となって強制終了してしまう……。これはバグではなく、OSの仕組み(GDIリソース)に起因する、プロが必ず直面する問題なのです。
今日は、その壁を突破し、システムが自ら「限界」を察知して、安全に再起動しながら処理を継続する「自己修復型オートメーション」の極意を伝授します。ここをクリアすれば、あなたはもう単なる「マクロ使い」ではなく、エンジニアへの階段を駆け上がることになりますよ。
1. なぜ、大量処理は途中で「力尽きる」のか?
まず、敵の正体を知ることから始めましょう。
AutoCADで図面を開くたびに、Windowsは画面を描画したり、線を引いたりするための「道具(リソース)」を割り当てます。これをGDI(Graphics Device Interface)オブジェクトと呼びます。
図面を閉じても、プログラムの書き方によっては、この「道具」が机の上に散乱したまま(メモリリーク)、片付けられないことがあります。
GDIリソースのイメージ図
- 正常時: 机(メモリ)は広く、道具(GDI)を使い終わったらすぐ片付けている。
- 異常時: 道具(GDI)が机の上にどんどん積み上がり、新しい道具を置くスペースがなくなる。
- 限界: 机がいっぱいになり、AutoCADは「もう何も描けない!」とパニックを起こして停止する。
これを防ぐには、「机が散らかりすぎてきたら、一度作業を中断して、机を綺麗に(AutoCADを再起動)する」という賢い管理ロジックが必要なのです。
2. プロフェッショナルの設計思想:Master-Worker パターン
ここで、非常に重要な設計の転換点があります。
「AutoCADの中にあるVBA」だけで完結させようとしてはいけません。なぜなら、AutoCADがクラッシュした瞬間、その中で動いているVBAも一緒に死んでしまうからです。
プロは、役割を分けます。
1. Master(司令塔): Excel VBA や VBScript など、AutoCADの「外」で動くプログラム。
2. Worker(作業員): AutoCAD 本体。
司令塔(Master)が、「次は3番目の図面だ。あ、そろそろ机が汚れてきたな。一度AutoCADを閉じて、再起動してから4番目に取り掛かろう」と判断するのです。
3. 実践:自己修復型オートメーションの実装例
ここでは、もっとも現実的で導入しやすい「Excel VBAを司令塔(Master)にする」方法を紹介します。
準備するもの
- Excel(図面リストを管理する)
- Windows API(GDIリソースを監視するために使用)
【コード例】GDIリソース監視型・連続図面処理エンジン
このコードは、Windows APIを使って現在のGDIオブジェクト数を取得し、一定数を超えたらAutoCADを安全に再起動する仕組みの骨組みです。
' --- Windows API の宣言 (GDIリソースを取得するために必要) ---
If VBA7 Then
Declare PtrSafe Function GetGuiResources Lib "user32" (ByVal hdc As LongPtr) As Long
Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Else
Declare Function GetGuiResources Lib "user32" (ByVal hdc As Long) As Long
Declare Function GetDesktopWindow Lib "user32" () As Long
End If
' --- 設定定数 ---
Const GDI_THRESHOLD As Long = 9000 ' GDIリソースがこれを超えたら再起動(環境に合わせて調整)
Sub MasterController()
Dim dwgList As Variant
Dim i As Long
Dim acadApp As Object
Dim currentFile As String
Dim gdiCount As Long
' 1. 処理対象の図面リストを取得 (ExcelのA列にパスが並んでいる想定)
dwgList = ThisWorkbook.Sheets(1).Range("A1:A" & Cells(Rows.Count, 1).End(xlUp).Row).Value
i = 1
Do While i <= UBound(dwgList)
currentFile = dwgList(i, 1)
' 2. GDIリソースの状態をチェック
gdiCount = GetGuiResources(GetDesktopWindow())
Debug.Print "現在のGDI使用量: " & gdiCount
' 3. リソースが限界に近いか判定
If gdiCount > GDI_THRESHOLD Then
Debug.Print "⚠️ リソース枯渇の兆候を検知。AutoCADを再起動します..."
' AutoCADを安全に終了させる
On Error Resume Next
Set acadApp = GetObject(, "AutoCAD.Application")
If Not acadApp Is Nothing Then
' ※ 実際にはここで「未保存の図面がないか」等のチェックが必要
acadApp.Quit
Set acadApp = Nothing
End If
On Error GoTo 0
' 再起動を待つための待機
Application.Wait (Now + TimeValue("0:00:05"))
i = i - 1 ' インデックスを戻して、次のループで新しいAutoCADを立ち上げる
GoTo NextLoop
End If
' 4. 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
acadApp.Visible = True
' --- 図面処理のメインロジック ---
Call ProcessSingleDrawing(acadApp, currentFile)
' ------------------------------
i = i + 1
NextLoop:
Loop
MsgBox "すべての工程が完了しました!", vbInformation
End Sub
' 図面1枚あたりの処理(ここを個別に作り込む)
Sub ProcessSingleDrawing(ByRef acadApp As Object, ByVal filePath As String)
Dim doc As Object
On Error GoTo ErrHandler
' 図面を開く
Set doc = acadApp.Documents.Open(filePath)
' --- ここに本来の業務ロジックを書く (例: 属性値の書き換えなど) ---
Debug.Print "処理中: " & filePath
' ---------------------------------------------------------
' 保存して閉じる
doc.Close True
Set doc = Nothing
Exit Sub
ErrHandler:
Debug.Print "❌ エラー発生 (" & filePath & "): " & Err.Description
' エラー時は図面を保存せずに閉じるなどの安全策を
If Not doc Is Nothing Then doc.Close False
End Sub
4. プロが教える「ここが落とし穴」
このコードをベースに開発を進める際、以下の3点に注意してください。ここをクリアすれば、あなたのプログラムは「実戦級」になります。
① 「未保存の変更」への対策
リソース枯渇で再起動する際、もし作業中の図面があったらどうなるでしょうか? `acadApp.Quit` をいきなり呼ぶと、AutoCADが「保存しますか?」というダイアログを出して止まってしまいます。
対策: 必ず `doc.Close True`(保存して閉じる)を徹底し、作業中の図面が一つもない状態で `Quit` を実行するフローを組み込みましょう。
② GDI閾値(しきいち)のチューニング
`GDI_THRESHOLD` の値は、使用するPCのスペックや、図面の複雑さによって異なります。
対策: 最初は少し低めの値(例:7000)から始め、数時間の連続稼働テストを行って、最適な「安全圏」を見極めてください。
③ オブジェクトの解放(Set = Nothing)
VBAにおいて、最も多いメモリリークの原因は、使い終わったオブジェクトを放置することです。
対策: `Set doc = Nothing` や `Set acadApp = Nothing` を、オブジェクトのライフサイクルが終わるたびに明示的に行いましょう。これは「後片付けの習慣」です。
最後に:一歩先へ進むあなたへ
いかがでしたか?
「単に図面を開いて処理する」というレベルから、「システムの安定性まで設計する」というレベルへの飛躍。これが、プロフェッショナルとアマチュアを分ける境界線です。
最初は難しく感じるかもしれません。でも、大丈夫。まずは「リソースを監視する」という考え方を持つだけで、あなたの設計思想は劇的に進化しています。
エラーに負けず、一つひとつのオブジェクトを大切に扱う。そんな丁寧なコードが、やがて巨大で複雑なシステムを動かす力になります。
応援しています。さあ、次の自動化へ挑戦しましょう!
