プロジェクト保存は「祈り」ではなく「設計」である:ネットワーク障害に屈しない堅牢なVBA実装術
業務自動化の現場において、ネットワークドライブ上のプロジェクトファイルを扱う際、最も避けるべきは「保存失敗によるデータロスト」だ。
「保存ボタンを押して、エラーが出て、そのままExcelがフリーズする」。この悲劇を、あなたは何度経験しただろうか。多くの開発者はこれを「ネットワークの不調」という不可抗力で片付けるが、それは誤りだ。ネットワークの切断は、分散環境でシステムを運用する以上、必ず発生する「仕様」である。
今日は、Project VBA(MS Project)における保存処理を、単なるメソッド呼び出しから「防衛的な堅牢ルーチン」へと昇華させるための極意を伝授する。
—
なぜ「そのまま保存」が失敗するのか
Project VBAの `ProjectSaveAs` や `FileSave` メソッドは、同期的に動作する。ネットワーク越しにサーバーへ書き込む際、パケットロスやセッションタイムアウトが発生すれば、即座に例外(またはCOMエラー)を吐いて死ぬ。
ここでやってはいけないのが、安易な `On Error Resume Next` だ。エラーを隠蔽した結果、ユーザーは「保存された」と思い込み、数時間分の工数を失う。我々が構築すべきは、「切断を検知し、復旧を待ち、整合性を担保して再試行する」という自律的な生存戦略である。
—
極限の保存ルーチン:実装の要点
この実装では、以下の3つのレイヤーで防御を固める。
1. 接続確認(事前チェック): 保存前にパスが到達可能かを確認する。
2. 指数バックオフ(リトライ戦略): 即時再試行はサーバーに負荷をかけるだけだ。待機時間を増分させながら再試行する。
3. 状態の確定(ログ記録): 最終的に失敗した場合、どこで止まったかを確実にログに残す。
プロダクションコード:RobustSave
このコードを標準モジュールに配置し、保存処理の呼び出し元をこれに置き換えてほしい。
Option Explicit
‘ 保存試行回数
Private Const MAX_RETRIES As Integer = 3
‘ リトライ待機時間(秒)
Private Const RETRY_DELAY As Integer = 5
Public Sub RobustSave(ByVal proj As Project)
Dim retryCount As Integer
Dim isSaved As Boolean
retryCount = 0
isSaved = False
Do While retryCount < MAX_RETRIES And Not isSaved
On Error Resume Next
' ネットワークパスの生存確認(Dir関数による簡易チェック)
If IsPathAccessible(proj.FullName) Then
proj.Save
If Err.Number = 0 Then
isSaved = True
Else
Debug.Print "Save Failed. Error: " & Err.Description
End If
End If
On Error GoTo 0
If Not isSaved Then
retryCount = retryCount + 1
If retryCount < MAX_RETRIES Then
' サーバー負荷を考慮した待機
Application.Wait (Now + TimeValue("0:00:" & Format(RETRY_DELAY retryCount, "00")))
End If
End If
Loop
If Not isSaved Then
MsgBox "致命的なエラー: ネットワーク接続が不安定です。ローカルへ一時保存してください。", vbCritical
End If
End Sub
' パスが生存しているかを確認する関数
Private Function IsPathAccessible(ByVal filePath As String) As Boolean
Dim folderPath As String
folderPath = Left(filePath, InStrRev(filePath, "\"))
' Dir関数でフォルダの存在を確認
If Dir(folderPath, vbDirectory) <> “” Then
IsPathAccessible = True
Else
IsPathAccessible = False
End If
End Function
—
実務で生き残るための「大人の注意点」
1. ファイルロックの罠
ネットワークドライブ上のファイルは、他ユーザーが閲覧しているだけでロックがかかる場合がある。`RobustSave` はあくまで「ネットワーク経路」の回復を狙うものだが、排他制御エラーが発生した場合は、別名保存(`SaveAs`)を検討する勇気を持つこと。同じパスに固執すると、キャッシュの不整合でファイルが壊れる可能性がある。
2. データベース連携時のトランザクション
もしこのプロジェクトが、別途SQL Server等のデータベースと連携しているなら、VBAの保存失敗は「データベースとの不整合」を意味する。ファイル保存が成功した後にDBを更新するのか、あるいはその逆か。「保存」というアクションをアトミック(不可分)に扱う設計思想が、プロジェクトの信頼性を決める。
3. パフォーマンスの重み
ネットワーク越しの `Save` は重い。ループ処理の中で頻繁に呼び出すのは御法度だ。保存処理は「トランザクションの境界」として明確に定義し、ユーザーにストレスを与えないタイミング(処理終了直後など)で実行するようにフローを設計せよ。
—
最後に:エンジニアとしての矜持
VBAは「初心者向けのおもちゃ」ではない。適切に設計すれば、エンタープライズ環境でも十二分に機能する武器となる。
今回提示したリトライ処理は、単なるコード片ではなく、「システムは必ず失敗する」という前提に立つエンジニアの思考そのものだ。エラーを恐れるな。エラーを制御下に置くのだ。それが、あなたのツールを「動くもの」から「信頼されるインフラ」へと変える唯一の道である。
さあ、あなたのコードを今すぐアップデートし、不安定なネットワーク環境を支配下に置くがいい。
