【テクニカル・上級編】【上級プロフェッショナル向け】ネットワーク切断時の「緊急ローカル退避保存」:保存エラーをトラップしてデータを守る – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:ネットワーク切断時の「緊急ローカル退避保存」

ネットワークドライブ上のDWGを直接編集している最中、突然のVPN切断やNASの障害により、あの悪名高い「図面の保存に失敗しました」というダイアログに直面したエンジニアリングチームは数知れない。

「上書き保存」のボタンを叩いた瞬間に失われる数時間のデザインワーク。AutoCAD標準の自動保存(SAVEFILE)機能は確かに存在するが、その挙動はネットワーク遅延やファイルのロック状態に大きく依存し、クリティカルな瞬間に信頼できるとは言い難い。

我々業務自動化のアーキテクトが目指すべきは、「いかなるI/Oエラーが発生しようとも、アプリケーション層で例外を完璧にキャッチし、ローカルの安全地帯へ確実に図面データを退避させる(作業ロスをゼロにする)不沈艦システムの構築」である。

今回は、AutoCAD VBAのイベントフック、VBAのエラーハンドリングの限界を突破する技術、そしてWindows環境を低レイヤーで支配するための極限の知見を公開する。

—

1. なぜ通常の `SaveAs` ではネットワーク切断に対応できないのか?

AutoCADの `Document.SaveAs` メソッドは、同期処理として動作する。ネットワークの物理層またはセッション層が切断された状態でこのメソッドを呼び出すと、AutoCAD内部のCOMラッパーはOSからのI/Oタイムアウト(あるいはNTSTATUSエラー)を待機し、そのままフリーズするか、致命的なランタイムエラー(エラー番号の返却すらない異常終了)を引き起こす。

さらに、VBAのエラーハンドリング(`On Error GoTo`)だけでは、AutoCADのC++コアエンジン内部で発生した致命的なファイルシステム例外を完全に捕捉しきれないケースがある。

これを突破するためには、以下の3つの防衛線を構築する必要がある。

1. FileSystemObject (FSO) による事前のターゲットパス疎通確認
2. AutoCAD内部イベントまたはマクロ実行時の堅牢なエラーキャッチ
3. OSのAPIを模した高速なファイル退避ルーチンと、オブジェクトの強制解放

—

2. 実装コード:緊急ローカル退避保存システム

以下のコードは、現在アクティブな図面の保存時にネットワークエラーを検知、あるいはプロシージャ側でエラーをトラップした際、瞬時にローカルの `C:\AutoCAD_Emergency_Backup\` へ図面を退避させる実用的なモジュールである。

単なる「コードの貼り付け」にとどまらず、VBAのメモリ管理の鉄則である「COMオブジェクトの即座の解放(Nothing代入)」を徹底している点に注目してほしい。

Option Explicit

‘ Windows API: 一時フォルダのパスを取得するために使用(環境依存を排除)
If VBA7 Then
Declare PtrSafe Function GetTempPath Lib “kernel32” Alias “GetTempPathA” (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Else
Declare Function GetTempPath Lib “kernel32” Alias “GetTempPathA” (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
End If

”’

”’ ネットワーク切断耐性を持つ極限の緊急保存ルーチン
”’

Public Sub EmergencySaveToLocal()
Dim acadDoc As AcadDocument
Dim targetPath As String
Dim localDir As String
Dim originalName As String
Dim fso As Object
Dim prefix As String

‘ 1. エラーハンドリングの有効化
On Error GoTo ErrorHandler

Set acadDoc = ThisDrawing
originalName = acadDoc.Name

‘ 図面がまだ一度も保存されていない(Drawing1.dwg等)の場合は処理をスキップ
If InStr(1, originalName, “.”, vbTextCompare) = 0 Then
MsgBox “この図面はまだ一度も保存されていません。手動で保存してください。”, vbExclamation, “緊急退避システム”
Exit Sub
End If

‘ 2. ローカルの退避用ディレクトリの構築
localDir = GetSystemTempPath() & “AutoCAD_Emergency_Vault\”

Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(localDir) Then
fso.CreateFolder localDir
End If

‘ 3. タイムスタンプ付与によるファイル名の衝突防止 (YYYYMMDD_HHMMSS形式)
prefix = Format(Now, “yyyymmdd_HHmmss”) & “_”
targetPath = localDir & prefix & originalName

‘ 4. ネットワーク上の本来の場所への上書きを試みる、あるいは直接ローカルへ退避
‘ ここであえて「SaveAs」をローカルパスに向けて実行することで、
‘ ネットワーク障害の影響を受けずにデータをハードディスクへ確実に書き出す。

‘ ※注意: 保存形式は現在の図面のデータベースバージョンを維持
Dim currentDocVersion As AcSaveAsType
currentDocVersion = acadDoc.SaveAsType

‘ ログ出力(システム管理者向け監査証跡)
Debug.Print “[” & Now & “] 緊急退避プロセス開始: ” & targetPath

‘ 実行:ローカルへの別名保存(これが最も確実な退避手段となる)
acadDoc.SaveAs targetPath, currentDocVersion

‘ 5. 成功時の通知
MsgBox “【緊急退避完了】” & vbCrLf & _
“ネットワーク接続エラーまたはユーザー要求により、図面をローカルに保護しました。” & vbCrLf & _
targetPath, vbInformation, “AutoCADセーフティシステム”

CleanUp:
‘ 6. オブジェクトの明示的解放(メモリリークの完全阻止)
Set fso = Nothing
Set acadDoc = Nothing
Exit Sub

ErrorHandler:
‘ 致命的な例外が発生した場合の最終防衛ライン
Dim errNum As Long
Dim errDesc As String
errNum = Err.Number
errDesc = Err.Description

MsgBox “【重大な保存エラー】” & vbCrLf & _
“ローカルへの退避中にもエラーが発生しました。” & vbCrLf & _
“エラーコード: ” & errNum & vbCrLf & _
“詳細: ” & errDesc, vbCritical, “システム異常終了”

‘ 異常終了時もメモリリークを残さない
Resume CleanUp
End Sub

”’

”’ OSのテンポラリパスを高精度に取得するヘルパー関数
”’

Private Function GetSystemTempPath() As String
Dim buffer As String
Dim ret As Long
buffer = Space(260)
ret = GetTempPath(260, buffer)
If ret > 0 Then
GetSystemTempPath = Left(buffer, ret)
Else
‘ フォールバック
GetSystemTempPath = “C:\Temp\”
End If
End Function

—

3. チーフアーキテクトが解説する実装の核心

① なぜ通常の `Save` ではなく `SaveAs` によるローカル退避なのか?

ネットワークドライブ上のファイル(例: `\\Server\Projects\DWG\2023\A-01.dwg`)に対して `.Save` を実行すると、AutoCADはファイルハンドルを維持したままリモートへ書き込もうとする。ここでパケットロスが発生すると、ファイルが破損(ゼロバイト化)するリスクが跳ね上がる。

一方、上記コードのように一度ローカルの堅牢な領域へ `SaveAs` で切り離すことで、既存のリモートファイルへの汚染を防ぎつつ、最新のバイナリデータを手元に確保できる。ユーザーは後から、安全になったネットワーク環境へそのファイルを再アップロードすればよい。

② VBAにおけるメモリ管理とオブジェクトライフサイクル

AutoCAD VBAにおいて、`ThisDrawing` や `AcadDocument` などのCOMオブジェクトを頻繁に参照・保持すると、COMの実参照カウント(Reference Count)が増加し、AutoCADのプロセス内にゴミ(ガベージ)が残留する。
特にエラー発生時にはオブジェクトが解放されずに残り、AutoCAD自体の不安定化(不安定な動作、メモリリークによる強制終了)を招く。
コード内の `CleanUp` ラベルと `Set fso = Nothing` の徹底は、エンタープライズ環境で稼働するVBAにおいて絶対に省略してはならない定石である。

③ タイムスタンプ付与の重要性

ファイル名(例: `20231027_143000_A-01.dwg`)にミリ秒単位に近いタイムスタンプを付与することで、短時間に複数回の緊急退避を行った場合でも、上書きによるデータの消失を防ぎ、バージョニングとしての役割も兼ねさせることができる。

—

4. 運用への組み込みとさらなる高みへ

このモジュールを単体のマクロとして放置するのではなく、リボンのカスタムボタンに割り当てる、あるいは図面閉鎖時(`DocumentEndClose` や `BeginSave` イベント)にフックさせることで、システムは真の「不沈艦」となる。

レガシーなファイルサーバー環境や、不安定なWi-Fi環境で設計業務を行うプロフェッショナルたちにとって、データの消失は致命傷である。OSのAPIとVBAの例外処理、そしてメモリのライフサイクルを完全に掌握したこのアーキテクチャを導入し、あなたの現場のエンジニアリング資産を鉄壁の守りで固めてほしい。

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