【テクニカル・上級編】【初心者向け】AcadDocument.FullNameが空なら「未保存」:新規作成図面への上書き保存エラーを回避する判定ロジック – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見
第1回:未保存図面のトラップを完全無力化する `FullName` 判定ロジックの極意

長年、製造業やプラントエンジニアリングの現場で数千・数万枚規模の図面自動化パイプラインを構築してきた。その中で、新人エンジニアが最も頻繁に踏み抜き、システムを沈黙させる地雷がある。それが「新規作成された未保存図面に対する `.Save` メソッドの実行」だ。

今回は、AutoCAD VBAの根幹をなす `AcadDocument` オブジェクトのライフサイクル、そしてファイルパスの有無を利用した鉄壁の保存判定ロジックについて、実戦の現場で培った知見のすべてを公開する。

—

1. なぜ `.Save` は未保存図面の前で無力なのか?

AutoCAD VBAを触り始めると、誰もが最初に書くのがこのコードだろう。

‘ 【アンチパターン】絶対にやってはいけないコード
Sub DangerousSave()
Dim doc As AcadDocument
Set doc = ThisDrawing

‘ ここで突然エラーが起きる、あるいは意図しない挙動になる
doc.Save
End Sub

このコードがなぜ悪なのか。理由は単純だ。「まだ名前のついていない(ディスク上に実体のない)キャンバスに対して、どこへ保存しろと言っているのか」がAutoCAD側で解決できないからだ。

`AcadDocument.Save` は、厳密には「既存のファイルを上書き保存(Save)」するためのメソッドである。ファイルパスが確定していない(=一度も保存されていない)新規図面(例: `Drawing1.dwg`)に対してこれを実行すると、AutoCADのバージョンやモーダル状態によっては、予期せぬダイアログが表示されてVBAの実行がフリーズするか、最悪の場合はランタイムエラーを引き起こし、生成中の膨大なメモリデータが闇に消える。

シニアアーキテクトであれば、APIやメソッドを呼び出す前に「オブジェクトの状態(State)」を検証するガード節(Guard Clause)を設けるのは常識だ。

—

2. `FullName` と `Name` の決定的な違い

図面が保存されているか否かを判定するために、多くの初心者が `ActiveDocument.Name` を使いたがる。だが、これは罠だ。

  • `Name` プロパティ: ファイル名と拡張子のみを返す(例: `Drawing1.dwg`)。未保存であっても、AutoCADが勝手に割り振った仮称を返すため、保存済みかどうかの判別には使えない。
  • `FullName` プロパティ: ドライブレターを含む完全なパスを返す(例: `C:\Projects\2023\ABC-001.dwg`)。

未保存の図面において、`AcadDocument.FullName` は必ず「空文字列(`””`)」を返す。
この仕様こそが、我々が信頼できる唯一の真実である。

—

3. 実戦投入可能な「安全な保存」実装パターン

ここに示すのは、実務の現場で数百回のエラーテストを潜り抜けてきた、堅牢な保存ラッパー関数だ。単にエラーを防ぐだけでなく、ユーザーの操作性(UX)も考慮して設計している。

Option Explicit

‘ =================================================================00
‘ 凄腕エンジニアの知見が詰まった:安全な図面保存ルーチン
‘ =================================================================00
Sub SafeSaveCurrentDrawing()
Dim targetDoc As AcadDocument
Set targetDoc = ThisDrawing

‘ 1. ドキュメントの存在確認(念のためのNULLチェック)
If targetDoc Is Nothing Then
MsgBox “アクティブな図面が存在しません。”, vbCritical, “致命的エラー”
Exit Sub
End If

On Error GoTo ErrorHandler

‘ 2. FullNameの長さで「新規未保存」か「保存済み」かを判定
If targetDoc.FullName = “” Then
‘ 【未保存の場合】: SaveAsダイアログを強制し、ユーザーに保存先を選ばせる
MsgBox “この図面はまだ保存されていません。” & vbCrLf & _
“次のダイアログで保存先を指定してください。”, vbInformation, “ファイル保存の確認”

‘ AutoCAD標準の「名前を付けて保存」ダイアログを呼び出す
‘ ※ コマンドライン経由でなく、アプリケーションのSendCommand等を使う手法もあるが、
‘ バージョン依存性を排除するため、ここではユーザーに対話を促すか、
‘ あるいはVBAからダイアログ制御を行う。
Call InvokeSaveAsDialog(targetDoc)

Else
‘ 【保存済みの場合】: 既存パスに対して静かに上書き保存を実行
targetDoc.Save
‘ 冗長なメッセージボックスは業務効率を落とすため、ステータスバー活用がプロの流儀
ThisDrawing.Utility.Prompt “図面を上書き保存しました: ” & targetDoc.FullName & vbCrLf
End If

Exit Sub

ErrorHandler:
‘ 3. メモリリークや予期せぬ例外のキャッチ
MsgBox “保存処理中に予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”

‘ オブジェクト変数の明示的解放(VBAと言えども大規模システムでは必須)
Set targetDoc = Nothing
End Sub

‘ =================================================================00
‘ サブルーチン: 安全にSaveAsダイアログへ誘導するプロシージャ
‘ =================================================================00
Private Sub InvokeSaveAsDialog(ByRef doc As AcadDocument)
On Error GoTo DialogError

‘ AutoCADのモーダルコマンド「SAVEAS」を安全に実行
‘ 注: VBAから直接COM経由でファイルダイアログを叩くよりも、
‘ AutoCADのネイティブコマンドをSendCommandでキックする方が、
‘ DWGのバージョン互換性エラーを回避できる。
ThisDrawing.SendCommand “_.SAVEAS ”

Exit Sub
DialogError:
Err.Raise Err.Number, “InvokeSaveAsDialog”, “SaveAsコマンドの実行に失敗しました: ” & Err.Description
End Sub

—

4. チーフアーキテクトからの深掘り:メモリ最適化とレガシー環境の保守

このコード片は氷山の一角に過ぎない。AutoCAD VBAを大規模なシステム連携(C#製外形アプリケーションや、ExcelマクロからのCOMオートメーション制御)に組み込む場合、以下の「極限の知見」を忘れてはならない。

1. COMオブジェクトの明示的解放(`Set … = Nothing`)の徹底
VBAのガベージコレクションは頼りにならない。特に複数ドキュメント(`AcadDocuments` コレクション)を巡回してバッチ処理を行う際、ローカル変数として宣言した `AcadDocument` をループの終端で確実に `Nothing` に解放しないと、AutoCADのプロセス(`acad.exe`)がメモリ上にゾンビとして残り続け、次回の自動化バッチをクラッシュさせる。

2. 背景実行(Non-Modal / Background Publishing)時の罠
もしこのコードが、UIを持たないバックグラウンドプロセスや、外部のVBScript/C#からCOM経由で呼び出された場合、`ThisDrawing.SendCommand “_.SAVEAS “` はデッドロックを引き起こす。なぜなら、バックグラウンドではモーダルダイアログを描画するキャンバスが存在しないからだ。
外部連携システムから制御する場合は、`SendCommand` ではなく、純粋なCOMメソッドである `doc.SaveAs(Path, 形式)` を使用し、事前に `Path` が有効かどうかのWin32 API(`PathFileExists` など)によるバリデーションを挟むのが真のプロフェッショナルである。

—

総括

たかが「保存」の判定、されど「保存」の判定。
たった1行の `If targetDoc.FullName = “”` を軽視した代償は、現場のエンジニアが数時間かけて作り上げた設計データの消失という形で支払われることになる。

オブジェクトのライフサイクルを支配し、APIの挙動を完全に掌握した者だけが、止まらない・壊れない強靭なAutoCAD自動化システムを構築できる。今日の知見をあなたの開発環境に直ちに組み込み、レガシーなコードをアップデートしてほしい。

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