AutoCAD VBAを掌握する極限の知見
【第1回】図面の「読み取り専用」状態を判定し、書き込み不可時のエラーを未然に防ぐAcadDocumentの運用
レガシーシステムの最前線、あるいは過酷な社内ニッチインフラの構築において、AutoCAD VBAほど「信頼性と脆さが背中合わせ」にある技術も珍しい。
エラーハンドリングを怠ったマクロは、ネットワーク共有フォルダ上の図面が開かれた瞬間に沈黙し、未保存のデータを彼方へと連れ去る。
今回は、実務の現場で最も遭遇しやすく、かつ軽視されがちな「図面の読み取り専用(ReadOnly)状態の判定と、書き込み不可時の制御」について、APIの挙動とオブジェクトモデルの核心に踏み込みながら解説する。
—
1. なぜ `ReadOnly` プロパティの確認だけで安心してしまうのか
初心者は `ActiveDocument.ReadOnly` を見て「Trueなら処理をスキップする」というコードを書く。
だが、シニアエンジニアの視点から言えば、それは氷山の一角に過ぎない。
AutoCADのドキュメントライフサイクルにおいて、ファイルが「読み取り専用」として開かれる要因は多岐にわたる。
- 他ユーザーが同名ファイルを排他制御(NFS / SMBロック)で開いている場合
- ファイルシステムのアクセス権(ACL)により書き込みが拒否されている場合
- 明示的に `Open` メソッドの引数で読み取り専用を指定した場合
さらに恐ろしいのは、「VBAの実行中に図面の状態が変化する可能性」である。マルチユーザー環境のインフラストラクチャにおいて、判定した瞬間に読み取り専用であっても、次の瞬間には状況が変わっているリスクを想定しなければならない。真の堅牢性を手に入れるには、単なるプロパティチェックを超えた、防御的プログラミングの構築が不可欠となる。
—
2. 実務を生き抜くための堅牢な判定コード
以下のコードは、単に `ReadOnly` を見るだけでなく、ファイルロックの競合、ドキュメントの存在有無、そして万が一の書き込み失敗に対するセーフティネットを網羅した、実務投入レベルのコードブロックである。
Option Explicit
” =================================================================
” módulo: 堅牢なドキュメント状態検証モジュール
” 目的: 読み取り専用ファイルへの無謀な書込試行を完全にブロックする
” =================================================================
Public Sub ValidateAndProcessActiveDrawing()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
‘ 1. Applicationオブジェクトの安全な取得 (Early Binding推奨)
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application”)
If Err.Number <> 0 Then
MsgBox “AutoCADが起動していません。”, vbCritical, “致命的エラー”
Exit Sub
End If
On Error GoTo 0
‘ 2. アクティブドキュメントの存在確認
If acadApp.Documents.Count = 0 Then
MsgBox “処理対象となる図面が開かれていません。”, vbExclamation, “警告”
Exit Sub
End If
Set acadDoc = acadApp.ActiveDocument
‘ 3. フルパスの存在確認(未保存新規図面「Drawing1.dwg」などの対策)
If acadDoc.FullName = “” Or InStr(acadDoc.FullName, “\”) = 0 Then
MsgBox “この図面はまだディスクに保存されていません。先に保存してください。”, vbCritical, “処理中断”
Exit Sub
End If
‘ 4. ReadOnlyプロパティの厳密な評価
If acadDoc.ReadOnly Then
Call HandleReadOnlyState(acadDoc)
Exit Sub
End If
‘ 5. 書き込み権限の最終テスト(ファイル属性の低レイヤーチェック)
If Not CheckFileWriteability(acadDoc.FullName) Then
MsgBox “ファイルシステムレベルで書き込みが拒否されています。” & vbCrLf & _
“権限を確認してください。”, vbCritical, “アクセス拒否”
Exit Sub
End If
‘ — ここから安全に書き込み処理を開始できる —
Call ExecuteCoreBusinessLogic(acadDoc)
End Sub
” 読み取り専用時の分岐処理
Private Sub HandleReadOnlyState(ByRef doc As AcadDocument)
Dim msg As String
msg = “【警告】現在の図面は「読み取り専用」で開かれています。” & vbCrLf & _
“ファイル名: ” & doc.Name & vbCrLf & _
“パス: ” & doc.FullName & vbCrLf & vbCrLf & _
“自動処理による上書き保存を防ぐため、処理を中断します。”
MsgBox msg, vbExclamation, “ReadOnlyガード発動”
‘ 必要であれば、ここで別名保存(SaveAs)を促すロジックや、
‘ ログ出力システムへのフックを記述する
End Sub
” ファイルシステムの物理的な書き込み可能性を検証するヘルパー
Private Function CheckFileWriteability(ByVal filePath As String) As Boolean
Dim fso As Object
Dim fileObj As Object
On Error GoTo ErrorHandler
Set fso = CreateObject(“Scripting.FileSystemObject”)
If fso.FileExists(filePath) Then
Set fileObj = fso.GetFile(filePath)
‘ 読み取り専用属性(Bit 0)が立っていないか確認
If (fileObj.Attributes And 1) = 0 Then
CheckFileWriteability = True
Else
CheckFileWriteability = False
End If
Else
CheckFileWriteability = False
End If
Exit Function
ErrorHandler:
‘ 予期せぬIOエラー時は安全側に倒してFalseを返す
CheckFileWriteability = False
End Function
Private Sub ExecuteCoreBusinessLogic(ByRef doc As AcadDocument)
‘ 実際の重い処理(トランザクション制御やレイヤー操作など)
MsgBox “書き込み権限を確認しました。処理を続行します。”, vbInformation, “正常”
End Sub
—
3. チーフアーキテクトからの提言:メモリ最適化とCOMオブジェクトのライフサイクル
AutoCAD VBAにおいて、`AcadApplication` や `AcadDocument` などのCOMオブジェクトは、明示的に解放(`Nothing`代入)を行わないと、AutoCADのプロセス内に参照カウントが残存し、背後で「ゾンビプロセス」を引き起こす原因となる。
特に、複数図面をバッチ処理するシステムや、外部からAutoCADをドライビングする設計においては、オブジェクトのスコープと解放タイミングの制御が生死を分ける。
‘ 良い例:処理完了後は確実に参照を断つ
Set acadDoc = Nothing
Set acadApp = Nothing
この泥臭いまでのリソース管理の徹底こそが、何千時間も無人で稼働し続ける基幹系AutoCAD自動化システムの土台を支えている。
甘いコードは、いつの日か必ずメモリリークとファイルロックの悪夢となって開発者の元へ帰ってくる。妥協のないコード記述を常に心がけてほしい。
