【AutoCAD VBA極限解説】第4回:図面を開く前にファイルロックをかけろ!同時編集の悲劇を防ぐ堅牢な排他制御
開発プロジェクトのリーダーである私から、現場のエンジニアへ一つ問いたい。
「ネットワーク共有フォルダにあるDWGを複数人が同時に開き、知らずに上書き保存して前任者の変更が吹き飛んだ」……この悪夢のようなインシデントを、未だに「人間の注意力」だけで防ごうとしていないだろうか?
AutoCAD標準のファイルロック機能(`.LCK`ファイルや読み取り専用警告)は、確かに存在する。だが、あれは「ファイルを開いた瞬間」にしか機能しない。VBAで大量の図面をバッチ処理する際や、独自のワークフロー管理システムを構築する現場においては、「開く前の先手必勝の排他制御」が絶対に不可欠だ。
今回は、実務の現場で即座に使える、堅牢なファイルロック機構を備えたDWGオープン制御の極意を伝授する。
—
1. なぜ「開いてから気づく」では遅いのか?
素人がやりがちな実装はこうだ。
1. `Workbooks.Open` や `Documents.Open` でとりあえずファイルを開く。
2. 読み取り専用(Read-Only)で開かれたことを検知してエラー処理する。
これでは実務の自動化ツールとしては失格だ。
重たいDWGファイルをメモリ上にロードし、COMのオブジェクトを生成した挙句、「すでにロックされています」と弾かれるのは、マシンのリソースの無駄遣いであり、処理速度の観点からも極めて非効率である。
プロの設計とはこうだ:
「OSレベルのファイル共有モードを制御し、ファイルストリームを排他的に確保できるか確認してから、AutoCADに料理させる」
この一手間が、ネットワークトラフィックを削減し、予期せぬAutoCADのクラッシュを防ぐ盾となる。
—
2. 堅牢なファイルロック設計の勘所
VBAでこれを実現するためには、FileSystemObject(FSO)だけでは不十分だ。VSO(Visual Basic for Applications)の標準関数である `Open` ステートメントのファイルモードを活用し、OSレベルでの排他アクセス(`Lock Read Write`)を仕掛けるのが最も確実かつ軽量である。
アーキテクチャのポイント
- 事前排他テスト: 対象のDWGファイルをバイナリ/出力モードで一時的に開こうと試みる。
- 例外キャッチ: 他者が編集中(またはWindowsの別プロセスが掴んでいる)であれば、即座にトラップして処理を中断する。
- クリーンアップ: テストが開けたら即座に閉じ、AutoCADの正規のドキュメントオープンにバトンタッチする。
—
3. 【プロダクションコード】排他制御付き安全ドキュメントオープナー
実務の現場でそのままコピー&ペーストして組み込めるモジュールを公開する。エラーハンドリングとクリーンアップのライフサイクル管理を徹底した、チーフアーキテクト品質のコードだ。
Option Explicit
”’
”’ 安全にAutoCADで開くプロシージャ
”’
Public Sub SafeOpenDrawing(ByVal targetFilePath As String)
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 1. ファイルの存在確認
If Not fso.FileExists(targetFilePath) Then
MsgBox “指定されたファイルが存在しません。” & vbCrLf & targetFilePath, vbCritical, “ファイルエラー”
Exit Sub
End If
‘ 2. 排他ロックテスト(OSレベルでファイルが占有可能かチェック)
Dim fileNum As Integer
fileNum = FreeFile
On Error GoTo LockError
‘ 書き込み・読み込み両方を禁止するモード(Lock Read Write)で開くを試みる
Open targetFilePath For Binary Access Read Write Lock Read Write As #fileNum
‘ 成功した場合は即座に閉じる(ロックを解放)
Close #fileNum
On Error GoTo 0
‘ 3. AutoCADによる実際のオープン処理
Dim doc As AcadDocument
On Error GoTo OpenError
‘ ドキュメントコレクションに追加
Set doc = ThisDrawing.Application.Documents.Open(targetFilePath)
‘ アクティブウインドウの設定
doc.Activate
Debug.Print “正常にオープンしました: ” & targetFilePath
Exit Sub
LockError:
‘ 既に他のプロセス(別ユーザー、別AutoCAD)で開かれている場合
Close #fileNum
MsgBox “この図面は現在、他のユーザーによって編集中(またはロック)されています。” & vbCrLf & _
“同時編集によるデータ破損を防ぐため、処理を中断します。” & vbCrLf & vbCrLf & _
“対象ファイル: ” & targetFilePath, vbExclamation, “排他制御アラート”
Exit Sub
OpenError:
MsgBox “AutoCADエンジンでのファイルオープンに失敗しました。” & vbCrLf & _
“エラー詳細: ” & Err.Description, vbCritical, “AutoCADエラー”
End Sub
”’
”’
Public Sub Test_SafeOpen()
Dim samplePath As String
‘ ※実環境の共有パス等に書き換えてテストしてください
samplePath = “C:\AutoCAD_Data\SampleDrawing.dwg”
Call SafeOpenDrawing(samplePath)
End Sub
—
4. コードの解説とエンジニアリングの哲学
なぜこのコードが「プロダクション品質」なのか、その理由をロジカルに解説しよう。
1. `FreeFile` の使用:
ハードコードされたファイル番号(例: `#1`)を使用すると、他のアドインや古いコードとの競合を引き起こす。必ず `FreeFile` 関数でOSから空きチャネルを取得すること。
2. `Open … For Binary Access Read Write Lock Read Write`:
この構文により、ファイルへのアクセス権を完全にテストできる。もし誰かがファイルを開いている場合、この行で必ずトラップ(`LockError`)に飛び、無駄なAutoCADの起動プロセスを回避できる。
3. 確実なリソース解放:
エラー発生時であっても `Close #fileNum` を通るようにし、ファイルハンドルがOSに残余リークするのを防いでいる。これが抜けると、VBAセッションが落ちるまでファイルが解放されなくなるデッドロックの温床となる。
—
おわりに
業務自動化のツール開発において、動くだけのコードは素人でも書ける。しかし、「異常系に強く、リソースを汚さず、マルチユーザー環境の衝突をスマートに回避するコード」を書けるかどうかが、プロのエンジニアとアマチュアの分かれ道だ。
今回紹介した排他制御のパターンをあなたのプロジェクトに組み込み、チーム全体の図面資産をデータ破損の恐怖から守り抜いてほしい。
妥協のないコードで、次の現場を圧倒せよ。
