こんにちは!AutoCADの自動化の世界へようこそ。
先輩エンジニアの私と一緒に、日々の退屈な作業をスマートに片付ける仕組みを作っていきましょう。
さて、外部のプログラムからAutoCADを操作(COMオートメーション制御)していて、こんな壁にぶつかったことはありませんか?
「処理が終わって `AcadApplication.Quit` を実行した瞬間、AutoCADが勝手にポップアップを出して止まってしまう……」
原因は、図面に「ちょっとした変更(未保存)」が残っているからです。人間が操作している時は親切なアラートですが、夜間バッチや外部システムからの自動連携の最中にこれが起まると、システムがフリーズしたように完全停止してしまいます。
今回は、このシャットダウン時のトラブルを華麗に回避し、「ユーザーの介入なしで、未保存の図面を問答無用で破棄するか、あるいはスマートに強制保存してクリーンに終了させる」ための極限のテクニックを伝授します。
ここをクリアすれば、あなたのAutoCAD VBAスキルは間違いなくプロの領域に到達しますよ!
—
1. なぜ `Quit` メソッドは突然止まるのか?
AutoCADのドキュメント(`AcadDocument`)は、それぞれが「保存状態」のフラグを持っています。
もしあなたがコード内で図面をゴリゴリ書き換え、`Save` をしないまま `ThisDrawing.Application.Quit` (または外部VBAから `acadApp.Quit`)を叩いたとします。
AutoCADの内部エンジンは、こう考えます。
> 「おいおい、変更されたデータが消えちまうぞ!本当に保存しなくていいのか?ユーザーに確認を取らなきゃ!」
これが、あの憎き「変更を保存しますか? [はい(Y)/いいえ(N)/キャンセル(C)]」ダイアログボックスの正体です。外部連携プログラムにとって、このダイアログは「絶対に越えられない壁(デッドロック)」になります。
これを突破するには、ダイアログが出る前に、開いている全ての図面の生死(保存するのか、破棄するのか)をコード側で完全にコントロールし尽くす必要があります。
—
2. 解決へのアプローチ:Documentコレクションの掌握
AutoCADのアプリケーション(`AcadApplication`)の直下には、現在開いているすべての図面を管理する `Documents` コレクションが存在します。
シャットダウンを完全制御するためのアルゴリズムは非常にシンプルです。
1. すべての図面をループで巡回する
2. それぞれの図面が「変更されているか(`Saved = False`)」をチェックする
3. 破棄なら `Close False`、保存なら `Save` または `SaveAs` を明示的に実行する
4. すべての図面を閉じたら、最後に胸を張って `Quit` を実行する
これだけです。言葉にすると簡単ですが、ここには実務で絶対に外せない「安全装置」の思考が必要になります。早速、実際のコードを見ていきましょう。
—
3. 実装コード:未保存図面の一括破棄・強制終了パターン
以下のコードは、外部(ExcelやVBA単体)からAutoCADを操作し、トラブル一切なしで安全にプロセスをシャットダウンするための決定版です。
Sub ForceQuitAutoCAD()
Dim acadApp As Object
Dim acadDocs As Object
Dim doc As Object
Dim i As Long
On Error Resume Next
‘ すでに起動しているAutoCADのインスタンスを取得
Set acadApp = GetObject(, “AutoCAD.Application”)
If Err.Number <> 0 Then
MsgBox “AutoCADは起動していません。”, vbExclamation
Exit Sub
End If
On Error GoTo 0
‘ ドキュメントコレクションを取得
Set acadDocs = acadApp.Documents
‘ 開いている図面がなければ、そのまま終了
If acadDocs.Count = 0 Then
acadApp.Quit
Set acadApp = Nothing
Exit Sub
End If
‘ 【重要】全ての図面を上から順にチェックして処理する
‘ ※コレクションを操作しながら閉じる場合は、インデックスを後ろから(Countから1まで)回すのが鉄則です!
For i = acadDocs.Count To 1 Step -1
Set doc = acadDocs(i)
‘ デバッグ用:現在の図面名を表示
Debug.Print “確認中の図面: ” & doc.Name
‘ 変更が加えられているか? (SavedプロパティがFalseのとき変更あり)
If Not doc.Saved Then
‘ — パターンA:変更を完全に破棄する場合 —
‘ 引数の False は「変更を保存せずに閉じる」の意味です
doc.Close False
‘ — パターンB:強制保存する場合の代替えコード(必要に応じてコメント解除) —
‘ If doc.Path = “” Then
‘ ‘ まだ一度も保存されていない新規図面の場合は名前をつけて保存
‘ doc.SaveAs “C:\AutoCAD_Backup\” & doc.Name
‘ ‘ Else
‘ ‘ 既存のファイルなら上書き保存
‘ doc.Save
‘ ‘ End If
‘ doc.Close True
Else
‘ 変更がない図面はそのまま閉じる
doc.Close False
End If
Next i
‘ 全ての図面がクリーンに閉じられたので、エラーなくシャットダウンを実行
acadApp.Quit
‘ メモリ解放の作法
Set doc = Nothing
Set acadDocs = Nothing
Set acadApp = Nothing
MsgBox “AutoCADを安全に終了しました。”, vbInformation
End Sub
—
4. コードの深掘りと「ここだけの」重要知見
このコードには、シニアエンジニアとしてのこだわりと、AutoCADのCOM構造に特化した「罠の回避策」が詰まっています。
① なぜ「後ろから(`Count To 1 Step -1`)」ループさせるのか?
プログラミング初学者がやりがちなミスとして、`For Each doc In acadDocs` を使って図面を閉じようとするケースがあります。
コレクション内の要素をループ中に削除(`Close`)すると、コレクションのインデックスがズレてしまい、「一部の図面が閉じられずに残る」「メモリ例外エラー(=-2147467259など)でクラッシュする」という最悪の事態を引き起こします。
後ろから数えて消していく(逆順ループ)は、COMコレクションを安全に掃討するための絶対のテクニックです。
② `doc.Close False` の強力な効果
`Close` メソッドに `False` を渡すことで、AutoCADは「おっと、この図面の変更は全部忘れよう」と判断し、一切のダイアログを出さずにその図面をメモリから解放します。
もし自動化処理の中でエラーが起き、途中でマクロを中断したくなった時でも、この処理を挟んでおけばAutoCADが裏でゴーストプロセスとして残り続ける現象を防げます。
—
5. まとめ:ここをクリアすれば、自動化は怖くない!
今回は、`AcadApplication.Quit` 実行時の最大の難所である「未保存図面のハンドリング」について解説しました。
- シャットダウン前に、すべての `Documents` を逆順ループで監視する。
- `doc.Saved` プロパティで変更有無を判定する。
- 破棄するなら `doc.Close False` でダイアログを完全に封殺する。
この一連のシャットダウンシーケンスを自分のコードに組み込めるようになると、外部連携システムからの夜間バッチ処理や、数十枚の図面を一括変換するスクリプトの信頼性が劇的に向上します。
「動かなくなったときは、ダイアログの裏でAutoCADがユーザーの返事を待っている」――この本質さえ押さえておけば、もう怖いものはありません。
あなたのAutoCAD自動化ライフが、より快適でスマートなものになることを応援しています!それでは、また次の極限知見でお会いしましょう。
