【AutoCAD VBAを掌握する極限の知見】
`AcadDocument.FullName`が空なら「未保存」:新規作成図面への上書き保存エラーを回避する堅牢な判定ロジック
開発プロジェクトのリーダーである私のもとに、よくこんな相談が持ち込まれる。
> 「自動化マクロの最後に `ThisDrawing.Save` を入れたのに、新規図面で実行するとエラーで落ちるんです」
> 「なぜかデバッグが走って業務が止まってしまう。どう書けば安全なんですか?」
結論から言おう。初心者がやりがちな最大の罠は、「保存されているはずだ」というエンジニアの勝手な思い込みだ。
AutoCADを起動して最初に立ち上がる「Drawing1.dwg」などの新規作成図面には、まだファイルパスという概念が存在しない。そこに前準備なしで `Save` メソッドを叩けば、AutoCADのCOMインターフェースはパニックを起こし、ランタイムエラーを吐き捨てるか、最悪の場合は意図しない挙動を引き起こす。
今回は、この初歩的でありながら実務の現場で最も頻発する「未保存ファイルへの上書きエラー」を根絶し、プロダクション環境に耐えうる堅牢な保存制御ロジックをあなたに伝授しよう。
—
1. なぜ `Save` メソッド単体では危険なのか?
AutoCAD VBAのオブジェクトモデルにおいて、ドキュメントを制御する主役が `AcadDocument` であることは言うまでもない。このオブジェクトには、ファイルの保存状態を把握するためのプロパティがいくつか用意されている。
- `Name`: 図面名(例: “Drawing1.dwg”)を返す。
- `Path`: 図面が保存されているフォルダパスを返す。
- `FullName`: フォルダパスと図面名を合わせたフルパス(例: `”C:\Projects\2023\Drawing1.dwg”`)を返す。
ここで初心者が陥りやすい勘違いが、`Name` プロパティのチェックだ。
「`Name` に `Drawing1.dwg` が入っているから保存されているはずだ」と判断してはならない。新規図面であっても、AutoCADはデフォルトで仮の名前を割り当てる。そのため、`Name` だけを見て判定すると、未保存の図面を既存ファイルとして誤認してしまうのだ。
唯一絶対の真実:`FullName` または `Path` の空判定
図面が一度でもディスク上に保存されたかどうかを判定するリトマス試験紙、それは `FullName`(または `Path`)が長さ0の文字列(`””`)であるかどうか である。
- 未保存の新規図面: `ThisDrawing.FullName` = `””`
- 一度でも保存された図面: `ThisDrawing.FullName` = `”実際の有効なフルパス”`
この物理的な事実に基づき、コードの分岐を設計しなければならない。
—
2. 堅牢な保存制御ロジックのアーキテクチャ
実務で使える自動化ツールにおいて、エラーハンドリングはオプションではなく必須要件だ。未保存の図面に対して `Save` を実行しようとした場合、以下の仕様を満たすフローを構築すべきである。
1. 保存状態の検査: `FullName` が空か否かをチェック。
2. 分岐処理:
- 空の場合(未保存): いきなり保存するのではなく、ユーザーに安全な場所を選ばせるために `SaveAs` ダイアログを促す(または自動命名規則に従ってサイレント保存する)。
- 空でない場合(保存済み): そのまま `Save` を実行し、高速かつスマートに上書き保存を完了させる。
このロジックを組み込むことで、ユーザーの作業を中断させることなく、予期せぬクラッシュやデータ消失のリスクを完全に排除できる。
—
3. 【コピペ推奨】プロダクション品質のセキュア保存プロシージャ
以下に、現場の第一線で即座に使える、洗練されたVBAコードを提供する。エラー対策、ユーザーへの適切なフィードバック、そして明確なコメントアウトを網羅した、まさに「プロの仕事」だ。
Option Explicit
” ==========================================================================
” 処理名: SafeSaveDrawing
” 概要 : 新規図面(未保存)と既存図面を自動判別し、安全に保存処理を実行する
” 備考 : 業務自動化ツールの終了時や、中間バックアップ時に組み込んで使用する
” ==========================================================================
Public Sub SafeSaveDrawing()
On Error GoTo ErrorHandler
Dim targetDoc As AcadDocument
Set targetDoc = ThisDrawing
‘ 1. FullNameプロパティの検証(未保存判定のキーストローク)
If targetDoc.FullName = “” Then
‘ 【未保存図面の場合の処理】
MsgBox “この図面はまだ保存されていません。” & vbCrLf & _
“次のダイアログで保存先を指定してください。”, vbExclamation, “セキュア保存マネージャー”
‘ 注意: SendCommandでの保存ダイアログ呼び出しはタイミング問題を引き起こすリスクがあるため、
‘ 実務ではユーザーに強制するか、特定の命名規則で自動保存(SaveAs)させるアプローチも有効。
‘ 今回は標準的なUI操作を促すため、コマンドライン経由で名前を付けて保存を実行。
targetDoc.SendCommand “_.QSAVE ”
‘ ※もし完全自動で特定のパスに保存させたい場合は以下のように記述する:
‘ targetDoc.SaveAs “C:\AutoCAD_Backup\TempDrawing_” & Format(Now, “yyyymmdd_hhmmss”) & “.dwg”
Else
‘ 【保存済み図面の場合の処理】
‘ 既にパスが存在するため、そのまま上書き保存を実行
targetDoc.Save
‘ ログ出力(イミディエイトウインドウ)
Debug.Print “上書き保存成功: ” & targetDoc.FullName
End If
Exit Sub
ErrorHandler:
‘ 予期せぬCOMエラーやユーザーの保存キャンセル時のハンドリング
MsgBox “保存処理中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
‘ 実務ではここにログファイルへの書き込み処理などを追加する
End Sub
—
4. チーフアーキテクトからの実務アドバイス
このコードをただコピペするだけではなく、さらに一段上のエンジニアリングを目指すための知見を授けよう。
① バッチ処理(複数図面ループ)における注意点
もしあなたが `Application.Documents` をループさせて一括処理するマクロを書いている場合、新規作成されたまま非表示やアクティブな状態で放置されているドキュメントが混ざっている可能性がある。
その場合、`FullName = “” ` のドキュメントに対してうっかり `Save` を叩くと、バッチ処理全体がストップしてしまう。必ずループの頭でこの `FullName` チェックを挟み、未保存の図面をスキップするか、一時フォルダへ自動保存するフォールバック(代替処理)を実装すること。
② `QSAVE` コマンドの罠
コード内で `SendCommand “_.QSAVE “` を使っているが、これはAutoCADのコマンドラインに依存するため、モーダルダイアログが開いている最中や他のコマンドがアクティブな場合には失敗することがある。
純粋なVBAのオブジェクトモデルだけで完結させたい場合は、`SaveAs` メソッドの利用を強く推奨する。ただし、`SaveAs` はユーザーに確認ダイアログを出さずに上書きやファイル作成を行うため、既存ファイルを誤って上書きしないよう、事前にファイル存在チェック(`Dir` 関数など)を組み合わせるのがプロの流儀だ。
—
総括
たった一行のプロパティ確認 (`FullName = “”`)。
この差を理解しているかどうかが、あなたの作るAutoCAD VBAツールが「素人のオモチャ」で終わるか、それとも「現場を支える堅牢なエンタープライズツール」になるかの分かれ道だ。
細部へのこだわりを捨てるな。コードの美しさは、そのまま業務の信頼性に直結する。さあ、今すぐ自分のコードを見直し、この堅牢な設計を組み込んでほしい。
