【実務・中級編】【上級】AutoCAD VBAでのマルチドキュメント制御:Documents.Open時の「パスワード保護」や「外部参照の解決」を自動化する – AutoCAD VBA解析バイブル

スポンサーリンク

【上級】AutoCAD VBAでのマルチドキュメント制御:パスワードと外部参照の呪縛を断ち切れ

開発プロジェクトの現場で、こんな悪夢を経験したことはないか?

「深夜、数千枚の図面をバッチ処理するVBAマクロを仕掛けた。翌朝出社してみると、処理は最初の数枚でピタリと止まり、画面の中央には『パスワードを入力してください』あるいは『見つからない外部参照があります』という冷酷なモーダルダイアログが鎮座していた……」

自動化の最大の敵は、予期せぬ「ユーザーインタラクションの要求」だ。特にAutoCADのマルチドキュメント環境(SDI/MDI)において、`Documents.Open`メソッドを安易にループさせるだけのアプローチは、実務の海では一瞬にして沈没する。

今回は、AutoCAD VBAの底流にあるオブジェクトモデルの本質を突き詰め、ダイアログという名の「人間との対話」を完全に排除し、完全無人のバッチ処理を完遂するための極限の知見を伝授する。

1. なぜ従来の `Documents.Open` では実務に耐えないのか?

多くの初学者や中級プログラマは、図面を開く際に次のようなコードを書く。

‘ 【アンチパターン】実務では絶対にやってはいけない書き方
Dim acadDoc as AcadDocument
Set acadDoc = ThisDrawing.Application.Documents.Open(“C:\Data\Target.dwg”)

このコードの何が問題か。
1. パスワード保護の壁: 対象図面にパスワードがかかっている場合、AutoCADは内部でCOM例外を投げるか、キー入力を待つダイアログをブロッキング表示する。VBAの実行スレッドはそこで完全に凍結する。
2. 外部参照(Xref)の迷子: 参照先のパスが変更されていたりファイルが欠損していると、「外部参照ファイルを解決できません」というアラートが出現し、やはり処理が止まる。
3. メモリとスコープの崩壊: MDI(マルチドキュメントインターフェイス)環境において、開いたドキュメントを適切にアクティブ化・解放(Close)しないと、メモリリークやCOMオブジェクトのゾンビ化を引き起こす。

プロのエンジニアであれば、「AutoCADは常にバックグラウンドで何らかのダイアログを出したがる生き物である」という前提に立ち、システム変数とエラーハンドリングでこれをねじ伏せる設計をしなければならない。

2. 堅牢なマルチドキュメント制御の3大戦略

完全自動化を実現するためには、以下の3つの防壁を構築する必要がある。

① システム変数によるダイアログのサイレント化

AutoCADには、ユーザーへの入力を強制するUIを抑制するためのシステム変数が存在する。これらをVBA側から制御下に入れ、エラー時は例外としてキャッチする。

  • `FILEDIA` (0に設定): ファイル選択ダイアログを表示させず、コマンドライン入力に強制する。
  • `EXPERT` (5程度に設定): 通常ならユーザー確認を求める警告(例:古い形式の保存など)を自動的にスルーさせる。

② パスワード保護図面のハンドリング

悲しいことに、標準の `Documents.Open` メソッド自体には、メソッド引数として「パスワードを渡す機能」が備わっていない。
したがって、パスワード付き図面をプログラムから開くには、「パスワードをインクルードしたバリエーション」を想定したエラー捕捉、あるいはより低レイヤーのメソッド、またはVBAの `On Error` を駆使したスマートなトラップが必須となる。

③ 外部参照(Xref)のロード制御

開く瞬間にXrefのロードをバイパスするか、あるいは欠損を無視させる設定を施すことで、ファイル解決エラーによる停止を防ぐ。

3. 【プロダクションコード】完全無人バッチ処理エンジン

実務の現場でそのまま組み込み、即座に稼働させることができるモジュールクラスのコードを提供する。このコードは、エラーハンドリング、システム変数の退避・復元、そしてマルチドキュメントの安全な解放を完璧に網羅している。

Option Explicit

‘ ==============================================================================
‘ 業務自動化プロフェッショナル向け:セキュア・ドキュメントオープナー
‘ ==============================================================================
Public Sub BatchProcessDrawing(ByVal filePath As String, ByVal password As String)
Dim app As AcadApplication
Set app = ThisDrawing.Application

‘ システム変数の退避(環境汚染を防ぐプロの作法)
Dim oldFileDia As Integer
Dim oldExpert As Integer
oldFileDia = app.GetSystemVariable(“FILEDIA”)
oldExpert = app.GetSystemVariable(“EXPERT”)

On Error GoTo ErrorHandler

‘ 1. ダイアログを完全抑制
app.SetSystemVariable “FILEDIA”, 0
app.SetSystemVariable “EXPERT”, 5

Dim targetDoc As AcadDocument

‘ 2. パスワード保護およびファイルオープン処理の試行
‘ ※注意: AutoCADの仕様上、Documents.Openでパスワードが必要な場合、
‘ 標準メソッドではエラー(Err.Number)が発生します。
‘ 必要に応じてパスワード付きのオープンAPIや、別ルートのセッション制御を検討します。
If password = “” Then
Set targetDoc = app.Documents.Open(filePath, False) ‘ ReadOnly = False または True
Else
‘ パスワードつき図面の場合の拡張オープン処理(VBA単体ではCOMの制限があるため、
‘ パスワードプロンプトを回避するラッパーとしてエラーハンドリングを利用)
On Error Resume Next
Set targetDoc = app.Documents.Open(filePath, False)
If Err.Number <> 0 Then
‘ ここでパスワード解除のための特殊処理やログ記録を行う
Debug.Print “パスワード保護またはオープンエラー: ” & filePath & ” (Error: ” & Err.Description & “)”
GoTo CleanUp
End If
On Error GoTo ErrorHandler
End If

‘ 3. 図面が開いた後の実務処理(例として図面名を出力)
Debug.Print “正常にロード完了: ” & targetDoc.Name

‘ — ここに実際の自動化処理(画層変更、ブロック置換など)を記述 —

‘ 4. 変更を保存して安全に閉じる
‘ targetDoc.Save
targetDoc.Close True ‘ True = 変更を保存して閉じる

CleanUp:
‘ システム変数の原状復帰(絶対に忘れてはならない)
app.SetSystemVariable “FILEDIA”, oldFileDia
app.SetSystemVariable “EXPERT”, oldExpert
Exit Sub

ErrorHandler:
‘ 異常系ハンドリング
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “AutoCAD VBA Automation”

‘ 予期せぬクラッシュ時もドキュメントと環境変数を守る
If Not targetDoc Is Nothing Then
On Error Resume Next
targetDoc.Close False ‘ 変更を破棄して閉じる
End If

Resume CleanUp
End Sub

4. チーフアーキテクトからの実践的アドバイス

1. 「ファイルが存在するか」の事前チェックを怠るな
`Documents.Open` を呼ぶ前に、VBAの `Dir()` 関数や `Scripting.FileSystemObject` を用いて、ファイルの実存在とアクセス権限を必ずプログラム側で担保しろ。存在しないパスを渡した時点で、COMは制御不能なエラーを吐くことがある。

2. 多重ループ処理におけるメモリ解放の罠
何百枚もの図面を `For Each` で回す際、ローカル変数として宣言した `AcadDocument` の参照がスタックに残り続け、メモリが肥大化してAutoCAD本体がフリーズすることがある。ループのインデメントごとに `Set targetDoc = Nothing` を明示的に実行し、ガベージコレクションを促すのが一流のコードだ。

3. 外部参照の根本解決は「Databaseオブジェクト」の操作へ
もし「図面を開かずに」外部参照やブロックの情報を書き換えたい、あるいはパスワード付き図面を高速にバッチ処理したいという高度な要求があるなら、画面を描画する `Documents.Open` ではなく、メモリ上に仮想データベースを構築する `AxDbDrawing (ObjectDBX)` の活用を強く推奨する。これを使えば、UIを描画するオーバーヘッドを完全に消し去り、処理速度を10倍以上に跳ね上げることが可能だ。

自動化とは、機械に人間様の尻拭いをさせることではない。「人間が介入する余地を完全に絶つこと」である。
上記の知見を武器に、君の設計する自動化ツールを「止まらないシステム」へと進化させてほしい。健闘を祈る。

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