CADという設計資産の心臓部を扱う際、エンジニアが最も恐れるべきは「意図しないデータの改変」である。
数千枚の図面をバッチ処理で巡回し、情報を抽出する。あるいは、標準部品ライブラリとして定義されたDWGを参照する。こうした「参照系」の自動化において、書き込み権限を持ってファイルを開くことは、設計品質に対する重大なリスク、あるいはシステム全体のデッドロックを招く引き金となる。
私はこれまで、数多くのレガシーなVBA資産が「開いて、閉じる」という単純な動作の不備で、共有サーバー上のファイルをロックし続け、設計業務を麻痺させてきた光景を見てきた。
本日は、AutoCAD VBAにおける「読み取り専用(Read-Only)」オープンの真髄を解説する。これは単なる引数の指定ではない。システム全体の整合性を守るための「防壁」の構築である。
—
1. `Documents.Open` メソッドの深層
AutoCAD VBAにおいて図面を開く標準的な手段は `Documents.Open` メソッドである。まずはそのシグネチャを正確に理解することから始まる。
RetVal = object.Open(Name[, ReadOnly][, Password])
第2引数の `ReadOnly` に `True` を渡す。これ自体は初歩的な知識だ。しかし、シニアエンジニアが意識すべきは、このメソッドが呼び出された瞬間にAutoCADの内部メモリで何が起きているか、そして「もし開けなかった場合」の挙動である。
プロフェッショナルな実装の雛形
単に `Open` を呼ぶのではなく、エラーハンドリングとオブジェクトのライフサイクル管理を徹底した実装を以下に示す。
‘—————————————————————————————
‘ Procedure : OpenDrawingSafe
‘ Purpose : 図面を安全に読み取り専用で開く
‘ Author : Legendary Chief Architect
‘—————————————————————————————
Public Function OpenDrawingSafe(ByVal filePath As String) As AcadDocument
On Error Resume Next
Dim targetDoc As AcadDocument
‘ 1. ファイルの存在確認(基本的なガード)
If Dir(filePath) = “” Then
Debug.Print “Error: File not found. -> ” & filePath
Exit Function
End If
‘ 2. 読み取り専用(True)でオープン
‘ 第2引数をTrueにすることで、AutoCADは書き込みロックを取得しない
Set targetDoc = ThisDrawing.Application.Documents.Open(filePath, True)
‘ 3. オープン成否の判定
If Err.Number <> 0 Then
Debug.Print “Error: Failed to open drawing. Code: ” & Err.Number & ” Desc: ” & Err.Description
Err.Clear
Set OpenDrawingSafe = Nothing
Else
Set OpenDrawingSafe = targetDoc
End If
On Error GoTo 0
End Function
—
2. Windows API による「事前検知」の重要性
AutoCADの `Open` メソッドは重い。特に巨大なDWGファイルや、ネットワーク越しにアクセスする場合、メソッドを呼び出してから「実はファイルが既に他人に独占的に開かれていて、読み取り専用ですら開けない」といったエラーが返るまで、数秒のハングを伴うことがある。
極限までパフォーマンスを追求するなら、AutoCADのエンジンを動かす前に、Windowsのカーネルレベルでファイルの属性やロック状態をチェックすべきだ。
ファイル属性の取得 (Windows API)
‘ Windows APIの宣言
If VBA7 Then
Private Declare PtrSafe Function GetFileAttributes Lib “kernel32” Alias “GetFileAttributesA” (ByVal lpFileName As String) As Long
Else
Private Declare Function GetFileAttributes Lib “kernel32” Alias “GetFileAttributesA” (ByVal lpFileName As String) As Long
End If
Private Const INVALID_FILE_ATTRIBUTES = -1
Private Const FILE_ATTRIBUTE_READONLY = &H1
‘—————————————————————————————
‘ Purpose : ファイルがOSレベルで読み取り専用かチェックする
‘—————————————————————————————
Public Function IsFileSystemReadOnly(ByVal filePath As String) As Boolean
Dim attr As Long
attr = GetFileAttributes(filePath)
If attr <> INVALID_FILE_ATTRIBUTES Then
IsFileSystemReadOnly = ((attr And FILE_ATTRIBUTE_READONLY) <> 0)
End If
End Function
このように、VBAの外部にある「OSの真実」を参照することで、不必要なAutoCADの例外処理を減らし、堅牢なシステムを構築できる。
—
3. オブジェクト・ライフサイクルの厳密な管理
読み取り専用で開いたドキュメントであっても、メモリ上では確実にリソースを消費している。
バッチ処理で数千枚を回す場合、最も致命的なのは「ドキュメントを閉じ忘れること」だ。AutoCAD VBAの `Documents` コレクションは、閉じられない限りメモリを食いつぶし、最終的には `Out of Memory` または `Fatal Error` でプロセスを死滅させる。
確実なクローズと解放の作法
Public Sub ProcessDrawingsInBatch(ByVal filePaths As Collection)
Dim path As Variant
Dim doc As AcadDocument
For Each path In filePaths
‘ 読み取り専用で取得
Set doc = OpenDrawingSafe(CStr(path))
If Not doc Is Nothing Then
‘ — ここでデータ抽出等の処理 —
Debug.Print “Processing: ” & doc.Name
‘ 処理が終わったら即座に閉じる
‘ 第1引数にFalseを指定し、保存を破棄(読み取り専用なので当然だが、明示が重要)
doc.Close False
‘ オブジェクト参照の明示的な解放
‘ これを行わないと、COMオブジェクトの参照カウントが残り、ゴーストプロセスを招く
Set doc = Nothing
End If
Next path
End Sub
シニアエンジニアであれば、`Set doc = Nothing` を単なるおまじないだと思ってはならない。これは、AutoCADという巨大なCOMサーバーに対し、「私はもうこのリソースを必要としていない」と宣言する重要なシグナルである。
—
4. レガシー環境と最新環境の架け橋
AutoCAD VBAは長く安定した技術だが、それゆえに古いDWGバージョンとの互換性に直面する。
読み取り専用で開く際、古いバージョンのDWGは自動的に「更新が必要」と判断され、内部的に変更フラグ(`IsDirty`)が立つことがある。
読み取り専用で開いたはずなのに、`Close` 時に「変更を保存しますか?」というダイアログが出る。これは自動化システムにおいて最悪の「ユーザー入力待ち」停止だ。
そのため、必ず `doc.Close False` を徹底すること。これにより、内部的な状態がどうあれ、ディスクへの書き込みを物理的に遮断し、サイレントに処理を完遂させることができる。
—
結論:アーキテクトとしての視点
「読み取り専用で開く」という行為は、単なるプログラミングのテクニックではない。
それは、「システムがいかなる理由があろうとも、元データを汚染しないことを保証する」という、設計者への誓約である。
1. `Open` メソッドの引数を正しく制御する。
2. Windows APIを併用し、OSレベルの整合性を確認する。
3. `Close` と `Set Nothing` を徹底し、メモリリークを根絶する。
この3枚の盾を持つことで、あなたの開発するVBAシステムは、単なるマクロから「エンタープライズに耐えうる自動化基盤」へと昇華する。
現場からは以上だ。幸運を祈る。
