1. なぜ「読み取り専用」を完璧に制御しなければならないのか?
設計業務の現場において、VBAによる自動化ツールを作成する際、最も恐ろしい事故は何か?
構文エラーでプログラムが止まることでもなければ、処理に数分余計にかかることでもありません。「過去のマスター図面や他人が編集中のDWGファイルを誤って上書き・破損してしまうこと」です。
一括データ抽出や図面情報の参照ツールを作成する際、担当者は「見るだけだから大丈夫」と高をくくって図面を開きます。しかし、適切な保護措置をコードレベルで講じていない場合、以下の致命的なトラブルが発生します。
- ネットワーク共有上のDWGファイルに対するロック(.dwl/.dwl2)の発生:他ユーザーの編集をブロックしてしまう。
- 図面保存ダイアログの意図しないポップアップ:バッチ処理(大量図面の一括処理)が途中で停止する。
- VBAの異常終了に伴う未保存状態の残留および次回起動時の修復ダイアログ表示。
本稿では、AutoCAD VBAにおいて指定したDWGファイルを確実に「読み取り専用(Read-Only)」で開き、処理後に1ミリのフットプリントも残さず安全にクローズする極意を解説します。
—
2. `Documents.Open` メソッドの解剖とパラメータ制御
AutoCAD VBAで図面を開く際、基本となるのは `AcadDocuments` コレクションの `Open` メソッドです。
まずは標準的な構文を確認しましょう。
Set AcadDoc = ThisDrawing.Application.Documents.Open(Name, [ReadOnly], [Password])
| 引数名 | 型 | 説明 |
| :— | :— | :— |
| `Name` | String | 開くDWG/DXFファイルのフルパス。 |
| `ReadOnly` | Variant (Boolean) | `True` を指定すると読み取り専用で開く。省略時は `False`。 |
| `Password` | Variant | パスワード保護された図面の場合に指定。 |
アマチュアのコードでは、`ReadOnly` を省略して `Documents.Open(“C:\drawings\sample.dwg”)` とだけ書かれます。これが事故の原点です。
明示的に `ReadOnly:=True` を渡すことで、AutoCADはファイルに対して書き込み権限の取得を行わず、純粋な参照モードとしてメモリ上に `AcadDocument` オブジェクトを展開します。これにより、OSやネットワークレベルでの不必要な書き込みロックを最小限に抑えることが可能になります。
—
3. プロダクション環境で耐えうる堅牢なVBA実装パターン
実務で動かすコードには、単に `Open` を呼ぶだけでなく、「事前チェック」「エラーハンドリング」「後処理の保証」という3つの defensive programming(防御的プログラミング)が必要です。
以下に、そのまま実務ツールへ組み込める洗練された関数の例を示します。
Option Explicit
”
‘ 指定された図面ファイルを安全に「読み取り専用」で開き、処理を行うメインルーチン
‘
Public Sub ReadOnlyProcessExample()
Dim targetFilePath As String
Dim targetDoc As AcadDocument
‘ 対象図面のフルパス(環境に合わせて変更してください)
targetFilePath = “C:\CAD_Data\Master_Drawing.dwg”
‘ 1. 読み取り専用で安全にドキュメントを取得
Set targetDoc = OpenDocumentReadOnly(targetFilePath)
‘ ドキュメントの取得に失敗した場合は安全に離脱
If targetDoc Is Nothing Then
MsgBox “図面のオープンに失敗したため、処理を中断します。”, vbCritical, “エラー”
Exit Sub
End Sub
‘ —– 処理メインルーチン —–
On Error GoTo ErrorHandler
‘ (例)図面内の全文字(AcadText/AcadMText)の数をカウントする等の参照処理
MsgBox “図面 ‘” & targetDoc.Name & “‘ を読み取り専用で正常に開きました。” & vbCrLf & _
“現在のモデル空間オブジェクト数: ” & targetDoc.ModelSpace.Count, vbInformation, “処理完了”
ErrorHandler:
If Err.Number <> 0 Then
MsgBox “処理中にエラーが発生しました: ” & Err.Description, vbExclamation, “実行時エラー”
End If
‘ 2. 後処理:変更破棄を保証して確実に閉じる
CloseDocumentSafely targetDoc
End Sub
”
‘ DWGファイルを「読み取り専用」で安全に開く関数
‘ @param filePath 図面ファイルのフルパス
‘ @return 開いたAcadDocumentオブジェクト(失敗時はNothing)
‘
Public Function OpenDocumentReadOnly(ByVal filePath As String) As AcadDocument
On Error Resume Next
‘ — 事前チェック 1: ファイルの存在確認 —
If CreateObject(“Scripting.FileSystemObject”).FileExists(filePath) = False Then
MsgBox “指定されたファイルが存在しません:” & vbCrLf & filePath, vbCritical, “ファイル消失エラー”
Set OpenDocumentReadOnly = Nothing
Exit Function
End If
‘ — 事前チェック 2: 既にAutoCAD内で開かれていないか確認 —
Dim doc As AcadDocument
For Each doc In ThisDrawing.Application.Documents
If UCase(doc.FullName) = UCase(filePath) Then
‘ 既に開いている場合はそのインスタンスを返す(重複オープンによる衝突防止)
Set OpenDocumentReadOnly = doc
Exit Function
End If
Next doc
‘ — 読み取り専用モードでオープン実行 —
‘ 第2引数(ReadOnly)に True を明確に指定
Set doc = ThisDrawing.Application.Documents.Open(filePath, True)
If Err.Number <> 0 Or doc Is Nothing Then
MsgBox “図面を開く際にエラーが発生しました:” & vbCrLf & Err.Description, vbCritical, “オープンエラー”
Err.Clear
Set OpenDocumentReadOnly = Nothing
Else
Set OpenDocumentReadOnly = doc
End If
On Error GoTo 0
End Function
”
‘ ドキュメントを完全に保護して閉じるサブルーチン
‘ @param targetDoc 閉じる対象のAcadDocumentオブジェクト
‘
Public Sub CloseDocumentSafely(ByRef targetDoc As AcadDocument)
If targetDoc Is Nothing Then Exit Sub
On Error Resume Next
‘ 【重要】SaveChanges:=False を指定し、万が一の変更(システム変数の自動変更含む)も一切保存させない
targetDoc.Close SaveChanges:=False, NoPrompt:=True
Set targetDoc = Nothing
On Error GoTo 0
End Sub
—
4. 現場のプロが叩き込む「3つの注意点と最適化」
上記のコードを動作させるにあたり、さらに一歩進んだアーキテクチャの知識が必要です。
① 「読み取り専用」でも変更はメモリ上で発生する
`ReadOnly:=True` で開いたからといって、VBAから図面要素を修正できないわけではありません。
VBAコード上で `entity.Layer = “0”` と書けば、メモリ上の図面データは書き換わります。しかし、保存(Save)しようとした段階でAutoCADが「読み取り専用です」とエラーを返します。
つまり、処理終了時に `targetDoc.Close(SaveChanges:=True)` を呼び出してしまうと、プログラムは例外を投げて崩壊します。参照用途であれば、後処理関数にあるように `SaveChanges:=False` を徹底してください。
② 画面描画(GUI)のオーバーヘッドを削る
大量の図面を連続して「読み取り専用」で開き、データを抽出するバッチツールを作成する場合、図面が開くたびに画面が再描画(ズームやウィンドウ切り替え)されると、パフォーマンスが極端に低下します。
速度を劇的に向上させたい場合は、処理ループの前後に以下のように画面更新とグラフィックの制御を行ってください。
‘ 描画の抑制(画面のちらつき防止と処理速度の向上)
ThisDrawing.Application.ScreenUpdating = False
‘ — ここで大量の図面を ReadOnly で順次処理 —
‘ 処理完了後に描画を再開
ThisDrawing.Application.ScreenUpdating = True
ThisDrawing.Application.Update
③ OSレベルの「読み取り専用」属性とファイルロック(.dwl)の挙動
ファイル自体のOS属性が「読み取り専用」になっている場合や、ネットワーク上の共有フォルダで他人がすでに開いている場合、`Open` メソッドの第2引数を省略すると、AutoCAD側で「読み取り専用で開きますか?」というプロンプト(ダイアログ)が表示され、VBAの処理がストップすることがあります。
第2引数に `True` を明示的に渡しておけば、このUIダイアログを自動的にバイパスし、無言で安全な読み取り専用モードとして起動させることができます。これが「完全自動化」を実現するための鍵です。
—
5. まとめ:堅牢な設計がツールへの信頼を生む
AutoCAD VBAにおける「図面を開く」というシンプルな処理ひとつをとっても、プロフェッショナルのコードとアマチュアのコードには明白な差が現れます。
1. `Documents.Open` の第2引数に `True` を明示指定する。
2. 開く前に「ファイルの存在確認」と「既オープン判定」を実施する。
3. 閉じるときは `SaveChanges:=False` で変更を確実に切り捨てる。
この3原則を徹底することで、ユーザーのマスター図面を破壊するリスクを極限までゼロにし、安定して高速に稼働する社内自動化ツールの構築が可能になります。ぜひ、あなたのプロジェクトのベースコードとして活用してください。
