「保存できない!」の絶望を防ぐ。ReadOnly図面を救う、プロフェッショナルなリカバリ・ロジック
こんにちは。AutoCAD VBAの世界へようこそ。
「マクロの記録」を使って、ボタン一つで図面を操作できるようになってきた……。そんな、脱・初級者を目指す皆さんに、今日は「実務で本当に差がつく、エラーハンドリングの極意」をお話ししようと思います。
プログラミングにおいて、最も恐ろしいのは「エラーで止まること」ではありません。「エラーが起きたことに気づかず、ユーザーの大切な作業データが消えてしまうこと」です。
今回のテーマは、実務で必ずと言っていいほど直面する「読み取り専用(ReadOnly)で開いてしまった図面」の制御です。
1. なぜ「読み取り専用」が問題になるのか?
AutoCADで作業をしていると、以下のような状況で図面が「読み取り専用」として開かれることがあります。
- 他の誰かがその図面を編集中のとき(ネットワーク上の共有フォルダなど)
- ファイルの属性が「読み取り専用」に設定されているとき
- サーバーの権限設定により、書き込みが制限されているとき
この状態で、あなたが一生懸命に図面を修正し、最後に「保存」ボタンを押したとしましょう。すると、AutoCADは「読み取り専用です。名前を付けて保存しますか?」と聞いてきます。
もし、ここでマクロ(VBA)が単純に `ThisDrawing.Save` とだけ書いてあったらどうなるでしょうか?
エラーが発生してマクロが強制終了し、ユーザーは「あれ?保存できたっけ?」と不安なまま、作業内容を失ってしまうリスクがあるのです。
これを防ぐには、「保存する前に、その図面が書き込み可能かどうかを、プログラム自身が判断する」という知性が必要になります。
2. 設計思想:賢いエンジニアの「回避ルート」
単にエラーを無視するのではなく、以下のような「回避ルート(リカバリ・ロジック)」を組み込みます。
1. 状態の監視: `ThisDrawing.ReadOnly` プロパティを確認する。
2. 条件分岐:
- 書き込み可能なら $\to$ 通常通り `Save`。
- 読み取り専用なら $\to$ 強制的に「別名保存(SaveAs)」へとリダイレクトする。
3. 安全な保存先: 保存先は、元の場所ではなく、確実に書き込み権限がある「一時フォルダ(Temp)」などを自動選定する。
4. ユーザーへの通知: 「元のファイルは保存できませんでしたが、一時フォルダに保存しましたよ!」と優しく伝える。
3. 実装コード:プロフェッショナル・リカバリ・ルーチン
それでは、実際に現場で使えるレベルのコードを見ていきましょう。
このコードは、単なる「保存」ではなく、「状況に応じた最適な保存手段を選択する」高度なロジックを持っています。
Option Explicit
''' <summary>
''' 図面の保存を実行する。読み取り専用の場合は、一時フォルダへ別名保存を行う。
''' </summary>
Sub SmartSaveRoutine()
Dim dwgDoc As AcadDocument
Set dwgDoc = ThisDrawing
Dim originalPath As String
Dim newPath As String
Dim tempFolder As String
Dim timestamp As String
' 1. 現在の図面パスを取得
originalPath = dwgDoc.FullName
' エラーハンドリングの開始
On Error GoTo ErrorHandler
' 2. 読み取り専用(ReadOnly)かどうかを判定
If dwgDoc.ReadOnly Then
' --- 【読み取り専用時のリカバリ・ロジック】 ---
' タイムスタンプを作成(ファイル名の重複を防ぐため)
timestamp = Format(Now, "yyyymmdd_hhnnss")
' Windowsの一時フォルダを取得 (例: C:\Users\UserName\AppData\Local\Temp)
tempFolder = Environ("TEMP") & "\"
' 新しいファイル名を生成 (元のファイル名_日時.dwg)
' ※拡張子を除いた名前を取得するために、パス操作を行う
newPath = tempFolder & "RECOVERY_" & timestamp & "_" & GetFileNameWithoutExtension(originalPath) & ".dwg"
' ユーザーに状況を通知(重要!)
MsgBox "警告: この図面は読み取り専用です。" & vbCrLf & _
"作業内容を失わないよう、一時フォルダに別名保存します。" & vbCrLf & _
"保存先: " & newPath, vbExclamation, "リカバリ実行"
' 別名保存を実行
dwgDoc.SaveAs newPath
MsgBox "リカバリ保存が完了しました。作業を継続してください。", vbInformation, "完了"
Else
' --- 【通常保存ルート】 ---
dwgDoc.Save
MsgBox "上書き保存が完了しました。", vbInformation, "成功"
End If
Exit Sub
ErrorHandler:
' エラーが発生した場合の処理
MsgBox "保存中に予期せぬエラーが発生しました。" & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical, "致命的なエラー"
End Sub
''' <summary>
''' フルパスから拡張子を除いたファイル名を取得するヘルパー関数
''' </summary>
Private Function GetFileNameWithoutExtension(ByVal fullPath As String) As String
Dim posSlash As Integer
Dim posDot As Integer
' 最後の "\" の位置を探す
posSlash = InStrRev(fullPath, "\")
' 最後の "." の位置を探す
posDot = InStrRev(fullPath, ".")
If posSlash > 0 And posDot > posSlash Then
GetFileNameWithoutExtension = Mid(fullPath, posSlash + 1, posDot - posSlash - 1)
Else
GetFileNameWithoutExtension = fullPath
End If
End Function
4. コードの深層解説:ここが「プロ」のポイント
このコードが、単なる「マクロの記録」と何が違うのか。その本質を解説します。
① `ThisDrawing.ReadOnly` プロパティの活用
これは図面の「状態」を表すプロパティです。`True` であれば、いくら `Save` メソッドを呼んでも、AutoCADは「書き込み権限がない」とエラーを返します。これを事前にチェックすることで、「エラーが出ることを前提とした動き」ができるようになります。
② `Environ(“TEMP”)` による環境依存の解消
保存先を `C:\MyTemp` のように固定してしまうと、他の人のPCで動かしたときに「そんなフォルダはありません」とエラーになります。`Environ(“TEMP”)` を使うことで、実行しているユーザーのWindowsが用意している一時フォルダを自動的に見つけ出すことができます。これが、汎用性の高いプログラムを作るコツです。
③ `On Error GoTo ErrorHandler`(例外処理)
プロのコードには必ず「もしもの時の逃げ道」があります。ネットワークの切断や、ディスク容量不足など、プログラム側で予測できない事態が起きたとき、いきなりプログラムがクラッシュしてAutoCADごと落ちてしまうのを防ぎ、ユーザーに適切なメッセージを表示するための防波堤です。
④ オブジェクトのライフサイクルへの配慮
`SaveAs` を実行すると、図面の「現在のパス」は新しいファイルへと切り替わります。このコードでは、読み取り専用の状態を維持したまま、新しいファイルとして「命(データ)」を繋ぎ止める処理を行っています。
5. まとめ:一歩先のエンジニアへ
いかがでしたか?
「エラーが出たら止まる」のは初心者です。
「エラーが起きる状況を予測し、別のルートを用意しておく」のがプロフェッショナルです。
今回学んだ「プロパティによる状態判定」と「環境変数を使った動的なパス指定」は、AutoCAD VBAに限らず、あらゆるプログラミングに通じる極めて重要な概念です。
ここをクリアすれば、あなたの作るツールは「ただ動くもの」から「現場で信頼される道具」へと進化します。ぜひ、自分の業務に合わせてカスタマイズして使ってみてくださいね。
応援しています。次はもっと高度な、オブジェクトのメモリ管理についてお話ししましょう!
