DWLファイルを制する者は、AutoCAD自動化を制す:二重開きによるデータ破損を防ぐ堅牢な設計論
業務自動化の現場において、最も恐ろしいのは「プログラムのバグ」ではない。「意図しないデータの先祖返り(上書き)」だ。
複数の設計者が同じサーバー上の図面を共有する環境において、VBAによる自動処理(バッチ処理や自動更新スクリプト)を走らせる際、もし「誰かが開いている図面」に対して不用意に書き込み操作を行えば、その瞬間にデータの整合性は崩壊し、プロジェクト全体に甚大な損失を与える。
プロのエンジニアなら、エラーが出てから対処するのではない。エラーが起きる状況を、設計段階で「検知・遮断」する。
本記事では、AutoCADが生成する「ロックファイル(DWL/DWL2)」を監視し、図面ファイルの二重開きを未然に防ぐための、極めて堅牢な実装手法を伝授する。
1. 知っておくべき「番人」の正体:DWLとDWL2
AutoCADは、図面ファイル(`.dwg`)を開くと、同じディレクトリ内に一時的なファイルを作成する。これがDWL(Drawing Lock)ファイルだ。
- `.dwl`: 伝統的なロックファイル。
- `.dwl2`: 近年のAutoCADバージョンで生成される、より詳細な情報を持つロックファイル。
これらは「今、この図面は誰かが占有している」という物理的な証拠である。AutoCADが正常に終了すればこれらのファイルは自動的に削除されるが、クラッシュやネットワーク断絶が発生した場合、これらが残留することがある。
初心者は「ファイルが開いているか?」を判定するために、無理やりファイルを開こうとしてエラーをトラップするような、極めて非効率で不格好なコードを書く。しかし、アーキテクトはこう考える。
「ファイルそのものに触れる前に、その影(DWLファイル)を確認せよ」と。
2. 設計思想:なぜ「Try-Catch」では不十分なのか
多くの開発者が陥る罠が、`On Error Resume Next` を多用した「当たって砕けろ」式の実装だ。
' --- アンチパターン:プロフェッショナルが絶対に書かないコード ---
On Error Resume Next
Open targetPath For Binary Access Read Write As #1
If Err.Number <> 0 Then
MsgBox "ファイルが開いています"
End If
On Error GoTo 0
この書き方がなぜ「低品質」なのか。理由は3つある。
1. リソースの無駄: ファイルへのアクセス試行自体が、OSレベルでオーバーヘッドを生む。
2. 不完全な判定: ネットワークドライブ上のファイルの場合、アクセス権限の問題なのか、使用中なのかの判別が曖昧になる。
3. 責務の混濁: 「ファイルがロックされているか」という判定ロジックと、「エラー処理」が混ざり合い、コードの保守性を著しく低下させる。
我々が目指すべきは、「状態を確認する関数」と「業務ロジック」を完全に分離した設計である。
3. 実装:堅牢なロックチェック・モジュール
以下に、プロダクション環境(実務投入レベル)でそのまま利用できる、洗練された実装例を示す。ここでは、`Dir` 関数を用いて、高速かつ軽量にロックファイルの存在を確認するロジックを構築する。
Option Explicit
''' <summary>
''' 図面ファイルが他のプロセスによって使用中(ロック中)かどうかを判定する。
''' </summary>
''' <param name="dwgPath">対象となるDWGファイルのフルパス</param>
''' <returns>使用中の場合はTrue、安全な場合はFalse</returns>
Public Function IsDrawingLocked(ByVal dwgPath As String) As Boolean
Dim baseDir As String
Dim fileName As String
Dim dwlPath1 As String
Dim dwlPath2 As String
' 1. パスの整合性チェック
If dwgPath = "" Or InStr(dwgPath, "\") = 0 Then
Err.Raise vbObjectError + 513, "IsDrawingLocked", "無効なファイルパスが指定されました。"
Exit Function
End If
' 2. 拡張子を剥ぎ取り、ベースとなるファイル名を特定
' 例: C:\Data\Project.dwg -> C:\Data\Project
baseDir = Left(dwgPath, InStrRev(dwgPath, ".") - 1)
' 3. DWLおよびDWL2のパスを構築
dwlPath1 = baseDir & ".dwl"
dwlPath2 = baseDir & ".dwl2"
' 4. Dir関数による高速存在チェック
' Dir関数は、ファイルが存在しない場合に空文字("")を返す。
' ネットワーク遅延を考慮し、まずは軽量なDirで判定を行う。
If Dir(dwlPath1) <> "" Or Dir(dwlPath2) <> "" Then
IsDrawingLocked = True
Else
IsDrawingLocked = False
End If
' Note: 万が一、DWLは消えているがファイル自体がOpenされている特殊な状況を
' 考慮する場合は、ここで別途ファイルアクセス試行を組み込む設計も検討の余地がある。
End Function
''' <summary>
''' メインの業務ロジック例
''' </summary>
Public Sub SafeOpenProcess()
Dim targetFile As String
targetFile = "C:\Work\Drawing_A.dwg" ' 本来はダイアログやDBから取得
On Error GoTo ErrorHandler
' --- ステップ1: 事前チェック(Gatekeeper) ---
Debug.Print "Checking lock status for: " & targetFile
If IsDrawingLocked(targetFile) Then
' ロックされている場合は、即座に処理を中断し、ユーザーに通知する
MsgBox "【警告】図面は他のユーザーによって使用中です。" & vbCrLf & _
"編集を中断します。ファイル: " & targetFile, vbCritical, "二重開き防止"
Exit Sub
End If
' --- ステップ2: 業務処理の実行 ---
Debug.Print "File is safe. Proceeding to open..."
' ここに AutoCADでのOpen処理や、DBへのログ記録などを記述
' Documents.Open targetFile ...
MsgBox "処理が正常に完了しました。", vbInformation
Exit Sub
ErrorHandler:
MsgBox "予期せぬエラーが発生しました: " & Err.Description, vbExclamation
End Sub
4. エンジニアとしての「一歩先」の知見
このコードを実装するにあたり、さらにプロフェッショナルを目指すなら以下の3点に留意せよ。
① ネットワーク・レイテンシ(遅延)の考慮
ファイルサーバー(NAS等)を介して図面を管理している場合、`Dir` 関数のレスポンスはローカルディスクよりも遅れる。大量のファイルをループでチェックする場合、処理待ちが発生することを念頭に置き、ユーザーへの進捗表示(StatusBarへの表示など)を実装するのが親切な設計だ。
② データベースとの同期
もし、君が構築しているシステムが「図面管理データベース」と連動しているなら、「DB上のステータス」と「実際のDWLファイルの有無」の乖離が起こりうる。
- DB上は「編集中」だが、PCがクラッシュしてDWLが消えた。
- DWLはあるが、DB上は「未着手」になっている。
この矛盾をどう扱うか。理想的な設計は、「DWLファイルの存在を物理的な真実(Single Source of Truth)とし、DBのステータスをそれに追従させる」ことだ。
③ ログ出力の重要性
単に `MsgBox` で警告を出して終わらせてはいけない。業務ツールとして運用するなら、「いつ、誰が、どのファイルを開こうとして、ロックされていたために失敗したか」をテキストログ、あるいはDBに記録せよ。これが、後に発生する「なぜかファイルが更新されていない」という問い合わせに対する、最強の防御策となる。
結論
AutoCAD VBAにおける自動化は、単に「操作を自動化する」ことではない。「不測の事態を予測し、システムの整合性を守り抜く」ことまでが、エンジニアの責務である。
DWLファイルをチェックするという一見小さな実装が、プロジェクトの信頼性を決定づける。この「守りの設計」を、君のコードに組み込んでほしい。
