脱・マクロ記録係。AutoCAD VBAの「速度の壁」を破壊する、マルチインスタンス並列処理の極意
こんにちは。現場の自動化を支えるエンジニアの皆さん。
これまで「マクロの記録」から一歩踏み出し、VBAのコードを書き、図面操作を自動化することに成功してきた……そんな素晴らしい歩みを進めてきたあなたへ、今日は「次なるステージ」への招待状を送りたくてこの記事を書いています。
「図面1枚の変換なら数秒で終わる。でも、1,000枚あったら……?」
そう思った瞬間、あなたはエンジニアとして、単なる「作業の自動化」から「システムの設計」へと視座が上がった証拠です。
VBAには、避けては通れない「宿命」があります。それは「シングルスレッド(一度に一つのことしかできない)」という制限です。どれだけコードを最適化しても、AutoCADという巨大なアプリケーションが一つ動いている限り、処理は一本道。待ち時間は増える一方です。
今日は、この宿命を打破する「マルチインスタンス的アプローチ」を伝授します。VBScriptという「司令塔」を使い、複数のAutoCADを同時に起動させ、並列で図面を捌き切るアーキテクチャです。
準備はいいですか? ここをクリアすれば、あなたの自動化スキルは「現場の便利ツール」から「プロフェッショナルな業務基盤」へと進化しますよ。
1. なぜVBA単体では「速く」なれないのか?
まず、本質的な理由を理解しましょう。
通常のVBAマクロは、今開いているAutoCAD(`AcadApplication`)に対して「これをして、次にこれをして」と命令を送ります。これは、一人の料理人に、100人分の料理を順番に作らせている状態です。料理人がどれだけ手際よくても、物理的に一度に作れるのは一皿ずつ。これがシングルスレッドの限界です。
これを解決する究極の方法は、「料理人を増やすこと」です。
つまり、AutoCADというアプリケーションそのものを、PCのメモリが許す限り複数立ち上げ、それぞれに別々の図面を処理させる。これが「マルチインスタンス(並列処理)」の考え方です。
2. 全体設計図:司令塔(VBScript)と作業員(VBA)の分業
この仕組みを実現するには、役割を明確に分ける必要があります。
- 【司令塔】VBScript(外部スクリプト)
- 役割:大量の図面リストを読み込み、AutoCADを「複数」立ち上げる。
- 働き:各AutoCADに「この図面を、このバージョンで保存して、終わったら閉じてね」という命令を飛ばす。
- 【作業員】AutoCAD VBA(内部マクロ)
- 役割:渡された図面を実際に開き、`SaveAs`を実行し、自分自身を終了する。
アーキテクチャ図
[ VBScript (司令塔) ]
|-- (命令1) --> [ AutoCAD Instance #1 ] --> 図面Aを変換
|-- (命令2) --> [ AutoCAD Instance #2 ] --> 図面Bを変換
|-- (命令3) --> [ AutoCAD Instance #3 ] --> 図面Cを変換
このように、複数のAutoCADが同時に動くことで、CPUのマルチコアをフル活用し、処理時間を劇的に短縮できるのです。
3. 【実践】作業員(VBA)のコードを書く
まずは、AutoCADの中で動く「実務担当」のコードを作りましょう。
ポイントは、「命令を受け取ったら、潔く自分を終了させる」ことです。
' --- AutoCAD VBA側: Module1 ---
' 図面変換専用のプロシージャ
Public Sub ConvertDrawing(targetPath As String, savePath As String, dwgVersion As Integer)
On Error GoTo ErrorHandler
Dim doc As AcadDocument
Set doc = ThisDrawing ' 現在開いている図面を操作対象にする
' 1. 図面を開く(既に開いている前提だが、念のため)
' 2. 指定の形式で保存 (dwgVersionはAutoCADのバージョン定数)
' ※ SaveAsの引数はAutoCADのバージョンにより異なります
doc.SaveAs savePath, dwgVersion
' 3. 保存が終わったら、この図面を閉じる
doc.Close acSaveChanges
' 4. 非常に重要:作業が終わったらAutoCAD自体を終了させる
' これをしないと、メモリ上に「幽霊プロセス」が残ってしまいます
Application.Quit
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
' エラーが起きても、プロセスが残らないよう終了を試みる
Application.Quit
End Sub
【ここがプロの知恵!】
`Application.Quit` を忘れないでください。並列処理において、最も恐ろしいのは「処理が終わったはずなのに、タスクマネージャーに `acad.exe` が大量に残っている(ゾンビプロセス)」状態です。これはメモリを食いつぶし、PCをフリーズさせる原因になります。
4. 【実践】司令塔(VBScript)のコードを書く
次に、外部からAutoCADを操る「司令塔」を作ります。Windows標準のVBScriptを使用します。
ここでは、複数のAutoCADインスタンスを非同期(命令を出したら、完了を待たずに次へ行く)で起動させるテクニックを使います。
' --- VBScript側: Orchestrator.vbs ---
Option Explicit
Dim shell, acadPath, targetFiles, i
Set shell = CreateObject("WScript.Shell")
' AutoCADの実行ファイルパス(環境に合わせて書き換えてください)
acadPath = """C:\Program Files\Autodesk\AutoCAD 2024\acad.exe"""
' 処理したい図面リスト(本来はテキストファイルなどから読み込むのが理想)
targetFiles = Array("C:\Temp\Drawing1.dwg", "C:\Temp\Drawing2.dwg", "C:\Temp\Drawing3.dwg")
' ---------------------------------------------------------
' 並列処理のメインループ
' ---------------------------------------------------------
For i = 0 To UBound(targetFiles)
' AutoCADを起動し、特定のコマンド(マクロ)を実行させる
' ここでは簡略化のため、コマンドライン引数やスクリプトファイルを利用する手法を想定
' 本来は、AutoCAD起動後にCOM経由でVBA関数を叩きますが、
' 初学者のうちは「AutoCADのスクリプト機能(/b)」を併用するのが最も安定します。
Dim cmd
' AutoCADを起動して、指定のスクリプトを実行するコマンド例
' /b はスクリプトファイル(.scr)を実行するスイッチです
cmd = acadPath & " /b ""C:\Temp\convert_script.scr"""
' shell.Run の第2引数を 1 にするとウィンドウを表示、0 にすると非表示
' 第3引数を True にすると「終了を待機」してしまうので、並列化したい場合は False にする!
shell.Run cmd, 1, False
' 次の起動までのわずかなインターバル(PCへの負荷軽減)
WScript.Sleep 2000
Next
MsgBox "すべての起動命令を完了しました。処理が終わるまでお待ちください。"
【ここがプロの知恵!】
`shell.Run` の第3引数を `False` にするのが最大のポイントです。ここを `True` にしてしまうと、一つ目のAutoCADが閉じるまで次のAutoCADが起動しません。これでは「シングルスレッド」と同じになってしまいます。`False` にすることで、「命令を出したらすぐ次へ行く」という並列動作が可能になります。
5. 陥りやすいエラーと回避策(トラブルシューティング)
この高度な手法を使う際、必ず直面する壁があります。
① 「幽霊プロセス(Zombie Process)」問題
症状: タスクマネージャーを見ると、`acad.exe` が大量にあり、PCが重い。
原因: VBAの `Application.Quit` がエラーでスキップされた、あるいはVBScriptが強制終了した。
対策:
- 必ず `On Error GoTo` でエラー時も `Quit` が走るように設計すること。
- 定期的にタスクマネージャーで確認する癖をつけること。
② 「リソース不足」問題
症状: 10個同時に起動しようとしたら、AutoCADがエラーで落ちる。
原因: PCのメモリ(RAM)やCPUが、複数のAutoCADを同時に動かすパワーを持っていなかった。
対策:
- 「一度に起動する数」を制限するロジックを司令塔に入れましょう。
- 例えば、「5個起動したら、1つ終わるまで待つ」といった制御です。
③ 「COMエラー」
症状: `Object required` や `Automation error` が出る。
原因: すでに閉じようとしているオブジェクトに対して、命令を送ろうとした。
対策: オブジェクトのライフサイクル(生成 $\to$ 操作 $\to$ 解放)を意識し、`Set obj = Nothing` で明示的に解放する癖をつけましょう。
最後に:エンジニアとしての第一歩
いかがでしたか?
「VBAだけで頑張る」のではなく、「外部からシステムとして制御する」という考え方。これこそが、プロフェッショナルな業務自動化への扉です。
最初は難しく感じるかもしれません。エラーもたくさん出るでしょう。でも、そのエラーの一つひとつが、「コンピュータがどう動いているか」を教えてくれる貴重な教材です。
ここを乗り越えれば、あなたはもう「マクロを記録する人」ではありません。「業務プロセスを設計するエンジニア」です。
さあ、自信を持って、コードを書き進めてください。応援していますよ!
