【テクニカル・上級編】【初心者向け】AcadApplication.Captionを動的に変更し、バッチ処理中の「残り図面枚数」をタスクバー上でリアルタイムに確認する – AutoCAD VBA解析バイブル

スポンサーリンク

【AutoCAD VBAを掌握する極限の知見】AcadApplication.Captionの動的制御によるバッチ処理の可視化とプロセス管理

はじめに:なぜ「タイトルバーの書き換え」が実務で神格化されるのか

AutoCAD VBAを用いた大規模な図面の一括処理(バッチ処理)において、エンジニアが直面する最大のフラストレーションは何か。それは「ブラックボックス化」である。

数十、数百の図面を開き、レイアウトを調整し、属性(Attribut)を書き換えて保存・閉じる――。この一連のルーチンを`AcadDocument.Close`や`SaveAs`で回している最中、AutoCADの画面を非表示にしたり、ウィンドウを最小化したりすることは実務上多々ある。しかし、タスクバーやウィンドウ枠を見ても、ただ「AutoCAD」と無機質に鎮座しているだけで、今「全500図面中の何番目を処理しているのか」を知る術がない。進捗バーをフォームで作ろうものなら、そのフォームの描画コストやフォーカス喪失のバグに足をすくわれる。

ここで登場するのが、`AcadApplication.Caption` プロパティだ。

このプロパティを操作することで、AutoCADのメインウィンドウのタイトルバー、ひいてはWindowsのタスクバーに表示される文字列を動的にジャックできる。APIの深部を叩かずとも、オブジェクトモデルの根幹からOSのUIレイヤーへ直接情報を射出するこの手法は、レガシーなAutoCAD環境において最もコストパフォーマンスが高い「極限の進捗可視化ソリューション」である。

今回は、単なるプロパティの代入にとどまらず、メモリ管理、エラーハンドリング、そして実務の現場で絶対に破綻しない堅牢性を備えた、プロフェッショナル向けの実装コードを提示する。

オブジェクトモデルの深層:`AcadApplication.Caption` の挙動と制約

`AcadApplication` は、AutoCADプロセスそのものを抽象化した頂点オブジェクトである。その `Caption` プロパティは、通常「AutoCAD [バージョン] – [アクティブ図面名]」といった文字列を保持している。

これをVBAから上書きすると、ウィンドウのタイトルバーが即座に変化する。
しかし、シニアエンジニアとして知っておくべき極限の知見として、以下の仕様上の罠が存在する。

1. ドキュメント切替時の自動上書き:
AutoCADはアクティブなドキュメントが切り替わると、標準ではCaptionを勝手に書き換え直す仕様を持っている。そのため、バッチ処理中で図面を開閉・アクティブ化するたびに、意図した進捗文字列が上書きされて消去されるリスクがある。
2. メインスレッドの占有と描画遅延:
ループのたびに頻繁にCaptionを書き換えると、OS側のウィンドウメッセージキューが圧迫され、わずかではあるがパフォーマンスに影響を与える。数千回のループを回す場合は、毎回ではなく一定間隔(例:1図面処理ごと)で確実に更新し、かつ文字列の結合コストを最小限に抑える必要がある。

実装コード:実務に耐えうる堅牢なバッチ処理エンジン

以下のコードは、指定したフォルダ内の全DWGファイルを巡回し、処理進捗をリアルタイムで `AcadApplication.Caption` に反映させながらバッチ処理を行うプロシージャである。

Option Explicit

‘ =========================================================================
‘ ódulo名: MdlBatchProcess
‘ 概要 : AutoCAD VBAによる堅牢なバッチ処理とCaption動的制御の実装
‘ 著者 : チーフアーキテクト
‘ =========================================================================

Public Sub ExecuteBatchWithProgress()
Dim targetDir As String
targetDir = “C:\Work\AutoCAD_BatchData\” ‘ 処理対象フォルダ

If Dir(targetDir, vbDirectory) = “” Then
MsgBox “指定されたディレクトリが存在しません: ” & targetDir, vbCritical, “致命的エラー”
Exit Sub
End If

‘ 対象ファイルの収集(FSOを使用)
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim targetFolder As Object
Set targetFolder = fso.GetFolder(targetDir)

Dim colFiles As Object
Set colFiles = CreateObject(“System.Collections.ArrayList”)

Dim fileItem As Object
For Each fileItem In targetFolder.Files
If LCase(fso.GetExtensionName(fileItem.Name)) = “dwg” Then
colFiles.Add fileItem.Path
End If
Next fileItem

Dim totalFiles As Long
totalFiles = colFiles.Count

If totalFiles = 0 Then
MsgBox “処理対象のDWGファイルがありません。”, vbExclamation, “警告”
GoTo Cleanup
End If

‘ 元のCaptionを退避(処理終了後に復元するため)
Dim originalCaption As String
originalCaption = ThisDrawing.Application.Caption

‘ 画面描画の抑制(パフォーマンス劇的向上のための極意)
Dim oldEcho As Boolean
oldEcho = ThisDrawing.GetVariable(“CMDECHO”)
ThisDrawing.SetVariable “CMDECHO”, 0

‘ AutoCAD自体の画面更新をロックする場合(必要に応じて)
‘ ThisDrawing.Application.Visible = False ‘ 完全非表示にするならここ(タスクバーでのCaption確認がより重要になる)

On Error GoTo ErrorHandler

Dim i As Long
Dim currentFilePath As Variant
Dim targetDoc As AcadDocument

‘ — メインバッチ処理ループ —
For i = 0 To totalFiles – 1
currentFilePath = colFiles(i)

‘ 【核心】AcadApplication.Captionの動的書き換え(残り枚数と進捗率)
Dim progressStr As String
progressStr = “【バッチ処理中】 ” & (i + 1) & ” / ” & totalFiles & ” 枚完了 (” & _
Format(((i + 1) / totalFiles), “0%”) & “) – 処理中: ” & fso.GetFileName(currentFilePath)

ThisDrawing.Application.Caption = progressStr

‘ 図面を開く (Read-Onlyではなく通常オープン、必要に応じてReadOnly引数を変更)
Set targetDoc = Documents.Open(CStr(currentFilePath), False)

‘ —————————————————————–
‘ ここに実際の図面処理ロジックを記述(例:レイ和設定、属性変更など)
‘ —————————————————————–
Call ProcessSingleDrawing(targetDoc)

‘ 変更を保存して閉じる
targetDoc.Close True

‘ オブジェクト変数の明示的解放(メモリリーク防止の鉄則)
Set targetDoc = Nothing

‘ Windowsに制御を少し戻し、UIのハングを防ぐ
DoEvents
Next i

‘ 正常終了時のCaption更新
ThisDrawing.Application.Caption = “【バッチ処理完了】 全 ” & totalFiles & ” 枚の処理が正常終了しました。”
MsgBox “すべてのバッチ処理が完了しました。”, vbInformation, “完了”

GoTo Cleanup

ErrorHandler:
‘ 異常終了時のハンドリング
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー発生”

If Not targetDoc Is Nothing Then
On Error Resume Next
targetDoc.Close False ‘ 変更を破棄して閉じる
Set targetDoc = Nothing
On Error GoTo 0
End If

Cleanup:
‘ 環境変数の復元
On Error Resume Next
ThisDrawing.SetVariable “CMDECHO”, oldEcho
ThisDrawing.Application.Caption = originalCaption
On Error GoTo 0

‘ オブジェクトの明示的解放
Set colFiles = Nothing
Set targetFolder = Nothing
Set fso = Nothing
End Sub

Private Sub ProcessSingleDrawing(ByRef doc As AcadDocument)
‘ 個別図面に対する実処理のサンプル
‘ 例としてモデル空間のエンティティ数をイミディエイトに出力
Debug.Print “Processing: ” & doc.Name & ” | Entities: ” & doc.ModelSpace.Count

‘ 実務ではここでレイヤの統廃合やブロック属性の書き換えを行う
End Sub

チーフアーキテクトが説く「死守すべき設計思想」

上記のコードには、単なる「動くサンプル」を超えた、現場で生き残るためのアーキテクチャ上のこだわりが凝縮されている。

1. メモリ管理と `Set targetDoc = Nothing` の徹底

AutoCAD VBAにおいて最も恐ろしいのは、背後で稼働するObjectDBXやAcadDocumentインスタンスの参照カウントが解放されず、プロセスがメモリリークを起こす現象である。ループのたびに `Set targetDoc = Nothing` を明示し、さらにエラー発生時には確実にドキュメントを強制クローズして破棄する構造がなければ、数百枚の処理の途中でAutoCADごと沈没する。

2. 環境変数の退避と復元 (`CMDECHO`)

バッチ処理中にコマンドラインがガチャガチャと動くのを防ぐため、`CMDECHO` を `0` にしている。しかし、処理が途中で異常終了した場合にこれが戻らないと、ユーザーの通常作業時に致命的な操作感の悪化を招く。`On Error GoTo ErrorHandler` と `Cleanup` ラベルを用いた確実な状態復元(トランザクション的な考え方)は、プロのVBAプログラマの必須要件である。

3. `DoEvents` の適切な配置

OSにCPUサイクルを適度に譲渡するため、ループの末尾に `DoEvents` を挟んでいる。これにより、ユーザーがタスクバーにマウスオーバーした際や、Windowsが「応答なし」と誤認してウィンドウをグレーアウトさせる現象を防ぎ、タスクバー上のCaption(進捗率)がリアルタイムに滑らかに更新されるようになる。

おわりに:レガシーの限界を突破する知見

最新の.NET API (C# / VB.NET) やForge (Autodesk Platform Services) 全盛の時代においても、社内のローカル環境で「今すぐ、確実に、追加のライブラリなしで」動く自動化ツールが求められる場面は数多く存在する。

AutoCAD VBAはレガシーな技術と嘲笑されることもあるが、オブジェクトモデルの本質を理解し、OSのUI特性(今回で言えば `AcadApplication.Caption`)と巧みに結合させれば、モダンなシステムにも劣らない高いユーザビリティを持つバッチ処理基盤を構築できる。

コードの行数を減らすことではなく、「絶対に途中で止まらない、止まっても安全に復元する、状況がひと目でわかる」こと。それこそが、現場を知るシニアエンジニアが体現すべき最高峰のエンジニアリングである。

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