【AutoCAD VBA】「保存できない!」を防ぐ極意:未保存図面におけるFullNameの罠と安全な保存ロジック
こんにちは。AutoCAD VBAの世界へようこそ。
マクロの記録機能を使って「あ、これ自動化できそうだな」と感じた瞬間、あなたはエンジニアとしての第一歩を踏み出したことになります。素晴らしいですね。
しかし、記録したマクロをそのまま動かそうとして、ある日突然「実行時エラー」という冷たい壁に突き当たることがあります。特に、図面の保存(Save)に関連するエラーは、多くの初学者が最初に躓く「登竜門」のようなものです。
今日は、そのエラーの正体である「FullNameプロパティの罠」について、その仕組みと、プロが書く「絶対に止まらないコード」の書き方を伝授しましょう。ここをクリアすれば、あなたのコードは一段上の、実戦的なレベルへと進化します。
1. なぜ、あなたの「Save」は失敗するのか?
まず、エラーが起きるシチュエーションを想像してみてください。
1. AutoCADを起動する。
2. 「新規作成」で新しい図面(Drawing1.dwg)を開く。
3. あなたが書いた「図面を保存するマクロ」を実行する。
4. ドカン! エラー発生!
なぜでしょうか? 「保存しろと言っているのに、なぜエラーになるのか?」と不思議に思いますよね。
原因は、AutoCAD(およびVBA)にとって、「まだ一度も保存されていない図面」は、コンピュータ上のどこにも存在していない「幽霊のような存在」だからです。
「Name」と「FullName」の違いを知ろう
ここで重要なのが、図面が持つ2つのプロパティの違いです。
- `Name` プロパティ: 図面ファイルの名前だけ(例: `Drawing1.dwg`)
- `FullName` プロパティ: ファイルの「住所(パス)」を含む完全な名前(例: `C:\Users\Desktop\Project\Drawing1.dwg`)
「新規作成」したばかりの図面は、名前(Name)はあっても、住所(FullName)が決まっていません。
`ActiveDocument.Save` という命令は、AutoCADに対して「今ある住所(FullName)に、そのまま上書き保存してね」と頼む命令です。しかし、住所が決まっていない図面に対して「今の住所に保存して!」と言っても、AutoCADは「えっ、どこに!? 住所がありません!」とパニックを起こしてエラーを出してしまうのです。
2. 解決策:二段構えのロジックを組む
この問題を解決するには、エンジニアらしい「条件分岐」が必要です。
「住所(FullName)があるなら Save、住所がないなら SaveAs」という風に、状況に応じて命令を使い分けるのです。
- `Save`: すでに存在するファイルを、そのまま更新する。
- `SaveAs`: 新しい名前と住所を指定して、初めてファイルとして書き出す。
図解すると、このようなロジックになります。
[図面を開く]
│
▼
[FullName(住所)は空っぽか?]
│
├── YES (未保存の新規図面) ──▶ [SaveAs を使って、場所と名前を指定して保存]
│
└── NO (すでに保存済みの図面) ──▶ [Save を使って、上書き保存]
3. 【実践】プロが書く「安全な保存」コード
それでは、実際に現場でそのまま使える、堅牢なコードを見てみましょう。
単にエラーを回避するだけでなく、もし未保存なら「どこに保存しますか?」とユーザーに問いかける、親切な設計にしています。
Sub SafeSaveDrawing()
Dim doc As AcadDocument
Set doc = ThisDrawing ' 現在アクティブな図面を対象にする
On Error GoTo ErrorHandler ' 万が一のエラーに備えてエラーハンドラを設置
' --- 判定フェーズ ---
' FullNameが空、あるいは特定のデフォルト状態かどうかをチェック
' 新規図面の場合、FullNameはパスを含まない状態や空の状態になることがあります
If doc.FullName = "" Or InStr(doc.FullName, "\") = 0 Then
' 【ケースA】未保存の図面の場合
MsgBox "この図面はまだ保存されていません。" & vbCrLf & _
"保存先を指定してください。", vbInformation, "保存の確認"
' SaveAs を呼び出す(ファイルダイアログを表示してユーザーに選ばせる)
' ※実務では、ここで保存先フォルダを自動決定するロジックを入れることも多いです
Dim fileSaveName As String
fileSaveName = Application.GetSaveAsFilename(InitialFileName:="新規図面.dwg", _
FileFilter:="AutoCAD Drawing (*.dwg), *.dwg")
' ユーザーがキャンセルを押さなかった場合のみ保存を実行
If fileSaveName <> "False" Then
doc.SaveAs fileSaveName
MsgBox "新規保存が完了しました。", vbInformation
Else
MsgBox "保存はキャンセルされました。", vbExclamation
End If
Else
' 【ケースB】すでに保存済みの図面の場合
' シンプルに上書き保存を実行
doc.Save
MsgBox "上書き保存が完了しました。", vbInformation
End If
Exit Sub
ErrorHandler:
' エラーが発生した場合の処理
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical, "実行エラー"
End Sub
コードの重要ポイント解説
1. `InStr(doc.FullName, “\”) = 0`:
これは「FullNameの中に `\`(パスの区切り文字)が含まれているか?」を確認しています。含まれていなければ、それはファイル名だけでパスがない(=未保存)と判断できる、非常に賢いテクニックです。
2. `Application.GetSaveAsFilename`:
いきなりプログラムで保存先を決めるのではなく、Windows標準の「名前を付けて保存」ダイアログを呼び出しています。これにより、ユーザーが直感的に操作できるようになります。
3. `On Error GoTo ErrorHandler`:
これが「プロの仕事」です。どんなに完璧なコードを書いても、ディスク容量不足やアクセス権限エラーは起こり得ます。エラーが起きたときに、真っ暗なエラー画面を出すのではなく、優しくメッセージを表示して終了させるための守りの構えです。
4. まとめ:オブジェクトの「状態」を意識しよう
今回の学びをまとめます。
- `Save` は「今いる場所」に保存する命令。
- `SaveAs` は「新しい場所」を作る命令。
- 未保存の図面には `FullName`(住所)がない ため、`Save` は失敗する。
- 「オブジェクトが今どういう状態にあるか?」 をプロパティで確認してから動くのが、安定した自動化の鉄則。
「マクロの記録」は、あくまで「操作の断片」を教えてくれるものです。しかし、それを「自動化システム」へと昇華させるには、今回のようにオブジェクトの性質(ライフサイクルやプロパティ)を理解し、条件分岐で制御する力が必要になります。
ここをクリアすれば、あなたのAutoCAD VBAは、単なる記録の再生機ではなく、頼もしい「相棒」へと進化します。
さあ、次のステップへ進みましょう。応援していますよ!
