AutoCAD VBAを掌握する極限の知見:Closeメソッドの引数「SaveChanges」徹底攻略
AutoCAD VBAによる図面処理の自動化において、最も初歩的でありながら、最も多くのエンジニアが実務の現場で足をすくわれるポイントがある。それが `Document.Close` メソッド、および `Documents.Close` メソッドにおける引数 `SaveChanges` の制御だ。
「とりあえず `True` にしておけば保存される」「`False` にすれば破棄される」――そんな浅薄な理解でコードを書いているうちは、シニアエンジニアとは言えない。図面の意図しない上書きによるデータ破損、無限ループするダイアログによるバッチ処理のフリーズ、そしてバックグラウンドプロセスにおけるメモリリーク。これらはすべて、この単一の引数と、背後にあるAutoCADのドキュメントライフサイクル管理を軽視した結果引き起こされる人災である。
本稿では、レガシー環境の保守から、完全無人のサーバーサイド連携までを見据えた、`SaveChanges` 制御の極限の知見を体系化する。
—
1. `Close` メソッドのメカニズムと `SaveChanges` の真実
AutoCADのドキュメント(DWG)は、単なるファイルではなく、メモリ上に展開された広大なオブジェクトグラフ(Database)である。これを破棄・クローズする際、CADエンジンは「変更が加えられたか(Modified)」を常に監視している。
`Document.Close` メソッドの構文は以下の通りだ。
object.Close(SaveChanges, [FileName])
引数の挙動の厳密な定義
- `SaveChanges` (Boolean)
- `True`: ドキュメントに変更がある場合、現在のファイル名で強制的に上書き保存して閉じる。新規図面の場合はファイルダイアログが(非表示モードでなければ)ポップアップする。
- `False`: 変更を一切保存せず、メモリ上の変更を破棄して閉じる。
- 省略時: AutoCADのデフォルト動作に依存するが、VBAからの実行時は多くの場合、ユーザーへの確認ダイアログ(プロンプト)のトリガーとなる。
初心者が陥る最大の罠:ダイアログの亡霊
バッチ処理中に `ActiveDocument.Close` を引数なしで実行したことはないか?
図面にわずかでも変更(例えば `Zoom Extents` すらデータベースをダーティにする要因になり得る)が加わった状態でこれを呼ぶと、AutoCADは画面の裏側で「変更を保存しますか? [はい(Y)/いいえ(N)/キャンセル(C)]」のダイアログを表示する。
当然、完全無人稼働すべきバッチプログラムはここで永遠に停止する。 タスクマネージャーから `acad.exe` を強制終了させる以外の選択肢が奪われる瞬間だ。
—
2. 実務で即座に使える「サイレント終了」パターン
意図しない上書きを防ぎ、かつ確認ダイアログを出さずに安全に図面を閉じるための鉄則は、「保存するか否かをコード側で完全にあらかじめ決定し、明示的にブール値を渡すこと」である。
以下に、実務の現場で即座に使える堅牢なプロシージャを示す。
Sub CloseActiveDocumentSafely(ByVal ForceSave As Boolean)
Dim targetDoc As AcadDocument
Set targetDoc = ThisDrawing.Application.ActiveDocument
On Error GoTo ErrorHandler
‘ 変更フラグ(Savedプロパティ)を事前に確認・制御するアプローチ
If ForceSave Then
‘ 強制保存して閉じる
targetDoc.Close SaveChanges:=True
Else
‘ 変更を破棄して強制終了する(保存漏れ防止)
targetDoc.Close SaveChanges:=False
End If
Exit Sub
ErrorHandler:
MsgBox “図面のクローズ中に致命的なエラーが発生しました: ” & Err.Description, vbCritical
‘ 必要に応じたログ出力やCOMオブジェクトの解放処理をここに記述
End Sub
`Saved` プロパティとの連携
もし「変更が加えられていない場合のみ、あるいはユーザーの意図した条件でのみ保存したい」という場合は、`Document.Saved` プロパティを事前にチェックするのがシニアの常套手段だ。
Sub SmartClose(doc As AcadDocument)
‘ データベースが変更されているか確認
If Not doc.Saved Then
‘ ここで独自のログ記録やバックアップ作成を行うことも可能
Debug.Print “変更が検知されました: ” & doc.Name
‘ 条件に応じた保存判定
Dim userChoice As VbMsgBoxResult
userChoice = MsgBox(“変更を保存しますか?”, vbYesNo + vbQuestion, “終了確認”)
If userChoice = vbYes Then
doc.Close SaveChanges:=True
Else
doc.Close SaveChanges:=False
End If
Else
‘ 変更がない場合はダイアログなしで安全に閉じる
doc.Close SaveChanges:=False
End If
End Sub
—
3. 大量図面一括処理(バッチ処理)におけるメモリ最適化とバージョン互換制御
複数図面をループ処理で開閉するアーキテクチャでは、`SaveChanges` の制御ミスはメモリリークおよびAutoCADプロセスの肥大化・クラッシュ直結する。
特にレガシーなAutoCAD環境(AutoCAD 2010〜2014世代など)では、ドキュメントを閉じた後もCOMラッパーがメモリ上に残存する現象が頻発する。これを防ぐための極限のコードパターンを提示する。
Sub BatchProcessDrawings(filePaths() As String)
Dim i As Long
Dim targetDoc As AcadDocument
Dim acadApp As AcadApplication
Set acadApp = ThisDrawing.Application
For i = LBound(filePaths) To UBound(filePaths)
‘ 1. 図面をサイレント(非表示またはバックグラウンド)でオープン
‘ ※実際にはDocuments.Openを使用
Set targetDoc = acadApp.Documents.Open(filePaths(i), ReadOnly:=False)
‘ 2. 業務ロジックの実行(例:レイアの整理、文字スタイルの統一など)
Call ProcessDrawingLogic(targetDoc)
‘ 3. 確実に変更を保存して閉じる(上書き保存)
‘ ※バージョン互換性を保つため、必要に応じてSaveAsで特定のDWG形式に落とし込むことも検討する
If Not targetDoc.Saved Then
targetDoc.Close SaveChanges:=True
Else
targetDoc.Close SaveChanges:=False
End If
‘ 4. ループごとのメモリ解放(極めて重要)
Set targetDoc = Nothing
‘ ガベージコレクションの誘発(VBA単体では完全ではないが、COM参照を断つ)
DoEvents
Next i
MsgBox “一括処理が完了しました。”, vbInformation
End Sub
Private Sub ProcessDrawingLogic(doc As AcadDocument)
‘ 実際の図面操作コード
‘ 例:全エンティティの走査など
Dim ent As AcadEntity
For Each ent in doc.ModelSpace
‘ 何らかの処理
Next ent
End Sub
バージョン互換上の注意点
`SaveChanges:=True` を実行すると、その時点のAutoCADのデフォルトファイルフォーマット(例: AutoCAD 2018形式など)で上書きされる。もし下位バージョン(例: AutoCAD 2004形式)での保存を厳格に義務付けられている環境であれば、`SaveChanges:=True` ではなく、明示的に `SaveAs` メソッドを呼び出してから `SaveChanges:=False` で閉じるべきである。
‘ 下位バージョン互換性を担保する場合の正しいイディオム
targetDoc.SaveAs PathName:=”C:\Output\Drawing.dwg”, Version:=ac2004_DWG
targetDoc.Close SaveChanges:=False ‘ すでにSaveAsしているので変更は破棄する
これを怠ると、上位バージョンで上書きされた図面が、現場の古いAutoCADで開けなくなるという致命的な業務障害(バージョン不整合エラー)を引き起こす。
—
4. チーフアーキテクトからの提言
AutoCAD VBAは強力だが、その背後にあるアプケーション、ドキュメント、データベースの階層構造を意識しないコードは、やがて現場を崩壊させる技術的負債となる。
`Close` メソッドの引数 `SaveChanges` は、単なる真偽値の選択ではない。それは「開発者がプロセスのライフサイクルを完全に掌握しているか、それともAutoCADの気まぐれなデフォルト動作に運命を委ねているか」を測るリトマス試験紙なのだ。
曖昧なコードを排除し、常に「保存されるべきか、破棄されるべきか、どのフォーマットで書き出されるべきか」をコードによって完全に支配せよ。それこそが、プロフェッショナルな業務自動化エンジニアの仕事である。
