【実務・中級編】【実務中級者向け】図面保存完了を検知する待機ループの実装:非同期書き込みによるエラーを防ぐ – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBA:なぜ「SaveAs」でエラーが起きるのか? 非同期書き込みを制する「真の待機ループ」実装術

AutoCADの自動化において、最も初歩的でありながら、多くのエンジニアが「運任せのコード」で放置している領域がある。それが「図面の保存待機」だ。

`ThisDrawing.SaveAs` を実行した直後、次の処理へ移ろうとして「ファイルが使用中」や「アクセス拒否」でクラッシュする。そんな経験はないだろうか?

多くの初心者はここで `Sleep` 関数を使って「3秒待つ」といった愚かな実装をする。だが、大容量図面やネットワークストレージ環境では、その3秒すら裏切られる。本稿では、AutoCADの内部ライフサイクルを理解した上で、確実に保存完了を検知する堅牢な実装を伝授する。

—

なぜ `SaveAs` は「即時完了」しないのか

AutoCADの `SaveAs` メソッドは、呼び出された時点で「保存を開始せよ」というコマンドをOS側に投げるが、それが物理的なディスク書き込み完了を意味するわけではない。

特に以下の条件下では、同期ズレが致命的なバグを誘発する。

  • ネットワークドライブへの保存: パケットの遅延や排他制御が絡む。
  • 大容量図面(重い外部参照など): 保存処理中のプロセスがロックを保持し続ける。
  • バックグラウンド保存機能: AutoCADのオプション設定により、保存が非同期で進む場合がある。

`DoEvents` を挟むだけのコードは、もはや「祈り」に近い。我々はエンジニアとして、「状態の監視」を行うべきだ。

—

堅牢な実装:FileSystemObjectを用いた「排他監視」

もっとも確実な方法は、保存されたファイルに対して「排他ロックが解除されるまで待つ」というロジックだ。VBAの `Scripting.FileSystemObject` を使い、ファイルが開けるようになるまでループを回す。

実装コード

このコードを標準モジュールに配置し、`SafeSaveAs` を呼び出すように設計せよ。

Option Explicit

‘ 保存待機のための安全なラッパー関数
Public Sub SafeSaveAs(doc As AcadDocument, filePath As String)
On Error Resume Next

‘ 保存実行
doc.SaveAs filePath

‘ 保存が完了するまで最大10秒間、排他ロックの解除を監視する
If Not WaitForFileReady(filePath, 10) Then
Err.Raise vbObjectError + 1001, “SafeSaveAs”, “保存完了を検知できませんでした。ファイルがロックされています。”
End If

On Error GoTo 0
End Sub

‘ ファイルが書き込み可能になるまで待機する関数
Private Function WaitForFileReady(ByVal path As String, ByVal timeoutSeconds As Long) As Boolean
Dim fso As Object
Dim startTime As Double
Dim fileNum As Integer

Set fso = CreateObject(“Scripting.FileSystemObject”)
startTime = Timer

Do
‘ ファイルが存在するか確認
If fso.FileExists(path) Then
‘ 排他アクセス権を試行(ファイルを開こうとしてみる)
On Error Resume Next
fileNum = FreeFile
Open path For Binary Access Read Write Lock Read Write As #fileNum

If Err.Number = 0 Then
‘ エラーなし=ロック解除成功
Close #fileNum
WaitForFileReady = True
Exit Function
End If
Err.Clear
On Error GoTo 0
End If

‘ 0.5秒のインターバルを置く(CPU負荷軽減)
DoEvents
Sleep 500 ‘ 要Windows API宣言

Loop While (Timer – startTime) < timeoutSeconds WaitForFileReady = False End Function ---

プロダクション環境での重要設計指針

このコードをあなたのツールに組み込む際、以下の3点を忘れてはならない。

1. Sleep関数の宣言: VBAには標準でSleepがないため、Windows APIの `kernel32` を宣言すること。

#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
#End If

2. タイムアウトの設計: タイムアウト時間は、図面のサイズに応じて可変にするのが賢い。数MBなら2秒、数百MBなら15秒といった具合だ。定数で固定してはいけない。
3. エラーハンドリングの徹底: `SafeSaveAs` が失敗した際、作成中のファイルが破損していないかをチェックする処理(存在チェックとサイズ確認)を後続に置くこと。

結論:自動化は「待機」に宿る

多くのスクリプトが、処理の「実行」部分に注力し、「状態の確認」を怠る。しかし、AutoCADのような重いアプリケーションを操作する場合、「次に進むための条件」をいかに厳密に定義できるかこそが、真の自動化エンジニアの腕の見せ所だ。

この「排他監視ループ」は、保存だけでなく、外部データベースへの書き込みや、出力したCSVの読み込みにも応用できる。コードをコピペして満足するのではなく、なぜこのループが有効なのか、その裏側にあるOSのファイルシステム制御を理解してほしい。

自動化の安定性は、美しいコードよりも「泥臭い確認」から生まれるのだ。

タイトルとURLをコピーしました