AutoCAD VBAを掌握する極限の知見:タイトルバーの動的制御によるUX向上とバッチ処理の堅牢化
数千枚規模の図面を一括処理するバッチプログラムを走らせたとき、AutoCADの画面がピクリとも動かなくなる。ユーザーから「これ、フリーズしているの?それとも動いているの?」と問われ、タスクマネージャーのCPU使用率を眺めて冷や汗をかいた経験は、レガシーシステムを背負うエンジニアなら一度や二度ではないはずだ。
AutoCAD VBAにおいて、バックグラウンド処理の進捗をユーザーに視覚的に伝えることは、単なる「親切心」ではない。システムの信頼性を担保し、誤った強制終了(タスクキル)による図面ファイルの破損を防ぐための極めて重要なアーキテクチャ上の要件である。
今回は、`AcadApplication.Caption` を動的に書き換え、さらにモダンなAPIの知見を応用した「フリーズと誤認させないバッチ処理」の実装パターンを、極限まで最適化されたコードとともに解説する。
—
1. なぜ `AcadApplication.Caption` なのか?
AutoCADのウィンドウ上部にあるタイトルバー(`AcadApplication.Caption`)は、標準ではアクティブな図面名や製品バージョンが表示されている。しかし、このプロパティはランタイムから書き換えが可能だ。
ユーザーはバッチ処理中、作業の手を止めて画面を注視することは稀であり、大抵は別のウィンドウで作業するか、進捗バーやタイトルバーの文字の変化を周辺視野で捉えている。モデルレスフォームを作成するリソースの無駄を省き、AutoCADのネイティブUIの一部をジャックして進捗を表示するこの手法は、オーバーヘッドが極めて少なく、レガシーなAutoCAD環境でも確実に動作する最も洗練されたアプローチと言える。
—
2. 実装:進捗表示付きバッチ処理エンジン
以下のコードは、指定フォルダ内の全DWGファイルを巡回し、開いて、何らかの処理(ここでは例としてレイヤのパージ)を行いながら、タイトルバーに進捗率(%)と処理ファイル名をリアルタイムに描画する実用コードである。
VBAの弱点である「画面描画の遅延」を抑制するため、適切なタイミングでの `DoEvents` の挿入と、メモリリークを防ぐためのオブジェクトの厳密な解放(ライフサイクル管理)を行っている。
Option Explicit
‘ メイン処理:バッチ処理のエントリポイント
Sub ExecuteBatchWithProgress()
Dim acadApp As AcadApplication
Dim sourceDir As String
Dim fso As Object
Dim folder As Object
Dim file As Object
Dim totalFiles As Long
Dim currentCount As Long
Dim originalCaption As String
‘ 1. アプリケーションインスタンスの取得と環境の退避
Set acadApp = ThisDrawing.Application
originalCaption = acadApp.Caption ‘ 終了時に元に戻すため退避
‘ 2. 処理対象フォルダの指定(ここでは例として固定パスまたはダイアログ)
sourceDir = “C:\AutoCAD_Batch_Target\”
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(sourceDir) Then
MsgBox “指定されたフォルダが存在しません: ” & sourceDir, vbCritical, “致命的エラー”
Exit Sub
End If
Set folder = fso.GetFolder(sourceDir)
totalFiles = 0
‘ 対象ファイルの総数をカウント(.dwgのみ)
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “dwg” Then
totalFiles = totalFiles + 1
End If
Next
If totalFiles = 0 Then
MsgBox “処理対象のDWGファイルが見つかりません。”, vbExclamation, “通知”
Exit Sub
End If
‘ 3. AutoCADの描画・警告抑制(パフォーマンス極限最適化)
With acadApp
.ScreenUpdating = False
.DisplayAlerts = False
End With
On Error GoTo ErrorHandler
currentCount = 0
‘ 4. バッチメインループ
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “dwg” Then
currentCount = currentCount + 1
‘ — タイトルバーの動的書き換え(進捗率の算出) —
Dim progressRate As Double
progressRate = Round((currentCount / totalFiles) 100, 1)
acadApp.Caption = “[” & progressRate & “%完了] (” & currentCount & “/” & totalFiles & “) 処理中: ” & file.Name
‘ OSに制御を戻し、タイトルバーの描画更新とフリーズ回避を行う
DoEvents
‘ — 図面のオープンと処理 —
Dim targetDoc As AcadDocument
Set targetDoc = acadApp.Documents.Open(file.Path, ReadOnly:=False)
‘ 【実務上の処理】例として全図面のパージを実行
Call ProcessDocument(targetDoc)
‘ 変更を保存して閉じる
targetDoc.Close SaveChanges:=True
‘ オブジェクト変数の即時解放(メモリ最適化)
Set targetDoc = Nothing
End If
Next
‘ 5. 正常終了時の処理
acadApp.Caption = originalCaption
acadApp.ScreenUpdating = True
acadApp.DisplayAlerts = True
MsgBox “バッチ処理が正常に完了しました。” & vbCrLf & “総処理数: ” & totalFiles & ” ファイル”, vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ 異常終了時も確実に環境を復元する(ゾンビプロセスやUIフリーズの防止)
acadApp.Caption = originalCaption
acadApp.ScreenUpdating = True
acadApp.DisplayAlerts = True
If Not targetDoc Is Nothing Then
On Error Resume Next
targetDoc.Close SaveChanges:=False
Set targetDoc = Nothing
End If
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ 図面ごとの個別処理をカプセル化するサブルーチン
Private Sub ProcessDocument(doc As AcadDocument)
On Error GoTo DocErrorHandler
‘ 例:未定義画層やブロックのパージ(3回実行して完全消去)
Dim i As Long
For i = 1 To 3
doc.PurgeAll
Next i
‘ ここにカスタムの図面修正ロジックを記述していく
Exit Sub
DocErrorHandler:
‘ 個別図面のエラーでバッチ全体を止めないためのローカルハンドラ
Debug.Print “図面処理エラー [” & doc.Name & “]: ” & Err.Description
End Sub
—
3. シニアエンジニアが押さえるべきアーキテクチャ上の要所
上記のコードは単に動くだけではない。大規模運用に耐えうるよう、以下の高度な設計思想が組み込まれている。
① `ScreenUpdating = False` と `DisplayAlerts = False` の両立
大量の図面を `Documents.Open` で開く際、AutoCADはデフォルトでビューポートの再描画や、フォント欠落などのダイアログを表示しようとする。これらを抑制せずにバッチを回すと、UIの描画コストだけで処理時間が何倍にも膨れ上がり、最悪の場合ダイアログがバックグラウンドでモーダル状態になりプロセスが完全にハングする。`DisplayAlerts = False` はこのサイレントクラッシュを防ぐ防壁となる。
② `DoEvents` のジレンマと制御
VBAはシングルスレッドで動作するため、重いループ処理を回すとOSから「応答なし」と判定される。これを回避するために `DoEvents` は必須だが、過剰な `DoEvents` は逆にパフォーマンスを低下させる。
ファイル単位(ループの1周ごと)で `DoEvents` を挟む設計であれば、オーバーヘッドを最小限に抑えつつ、タイトルバーの描画更新とユーザーからのマウス操作(キャンセルボタン等を作る場合の前提)を受け付ける絶妙なバランスを保つことができる。
③ 厳格なエラーハンドリングと「状態の復元」
バッチ処理の途中でエラーが発生した際、AutoCADのタイトルが書き換わったまま、あるいは `ScreenUpdating = False` のままクラッシュすると、ユーザーは絶望的な状況に陥る。
必ず `On Error GoTo ErrorHandler` を経由させ、イミディエイトウィンドウやメッセージボックスへの出力だけでなく、アプリケーションの状態(Caption、ScreenUpdating、DisplayAlerts)を確実に原状復帰させる構造がプロフェッショナルのコードの条件である。
—
4. 総括
VBAにおけるUIフィードバックは、リッチなWPFやWindows Formsを使わなければ実現できないわけではない。むしろ、AutoCADのオブジェクトモデルが持つネイティブなプロパティ(`AcadApplication.Caption`)を巧みにハックすることで、依存関係を増やさず、軽量かつ強靭なバッチ処理システムを構築できる。
現場のエンジニアとして、動くコードを書くことはスタートラインに過ぎない。「ユーザーに不安を与えず、例外時にも環境を汚さない堅牢性」を兼ね備えたコードこそが、あなたの組んだ自動化システムを社内で永続的に生き続けさせる唯一の武器となる。
