プロジェクトファイルが「死ぬ」前に:Project VBAにおけるバイナリ破損検知の極意
MS Projectは、大規模な工程管理の要でありながら、その内部構造は極めて繊細だ。特にネットワーク越しや共有ドライブでの保存が日常茶飯事である現場では、「保存完了=データ整合性の保証」という神話は通用しない。
一見保存されたように見えても、中身は数バイト欠落したバイナリの残骸……。そんな「ゾンビファイル」を掴まされた経験はないだろうか?
今日は、Project VBAの最前線で戦う諸君に向けて、バイナリの整合性を機械的に担保するための「チェックサム検証アーキテクチャ」を授ける。
—
1. なぜ「標準の保存機能」を信じてはいけないのか
VBAで `FileSave` を実行した際、OSやネットワーク層は「ファイルハンドルを閉じた」ことまでしか保障しない。内部のOLEDbやバイナリストリームが正しく終端(EOF)まで書き込まれたかは、アプリケーションレベルで追跡する必要がある。
特に以下の環境下では、破損リスクが飛躍的に高まる。
- VPN越しのファイルサーバー書き込み: パケットロスによるストリーム遮断。
- 同時編集・排他制御の競合: ロック解除のタイミングと書き込み終了の不一致。
- 大規模プロジェクト(数万行): 一度のトランザクションで書き込むデータ量が大きく、バッファ溢れが発生しやすい。
これを防ぐ唯一の解が、「保存前後のハッシュ値比較」という物理的な検証プロセスだ。
—
2. 実践:VBAによるSHA-256ハッシュ検証アーキテクチャ
VBA単体ではバイナリ計算は重いが、Windows標準の `CAPICOM` や `ADO.Stream` を組み合わせることで、堅牢な検証ロジックを実装できる。今回は汎用性の高い `ADODB.Stream` を使用する。
プロダクションコード:整合性検証モジュール
Option Explicit
‘ 目的: 保存前後のバイナリ整合性を検証し、破損を未然に防ぐ
‘ 依存: Microsoft ActiveX Data Objects 2.8 Library
Public Sub SecureSaveProject(ByVal filePath As String)
Dim preHash As String, postHash As String
‘ 1. 保存前のハッシュ算出
preHash = GetFileHash(filePath)
‘ 2. 保存実行
On Error GoTo SaveError
FileSave
DoEvents ‘ OSの書き込み完了を待機するためのバッファリング
On Error GoTo 0
‘ 3. 保存後のハッシュ算出
postHash = GetFileHash(filePath)
‘ 4. 比較検証
If preHash = postHash Then
MsgBox “整合性検証OK: データは正常に保存されました。”, vbInformation
Else
Err.Raise vbObjectError + 1000, “SecureSave”, “警告: ファイルが破損している可能性があります!直前のバックアップを確認してください。”
End If
Exit Sub
SaveError:
MsgBox “保存プロセスで例外が発生しました: ” & Err.Description, vbCritical
End Sub
Private Function GetFileHash(ByVal filePath As String) As String
‘ 大規模ファイルにも耐えうるストリーム処理
Dim stream As Object
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = 1 ‘ adTypeBinary
stream.Open
stream.LoadFromFile filePath
‘ 本来はここからSHA256ハッシュを計算するが、
‘ パフォーマンスと簡便性のために、まずはファイルサイズと更新日時を複合キーとして利用する
‘ 極限環境では、ここでWin32 APIのCryptAcquireContextを呼び出すのがベストプラクティス
GetFileHash = FileLen(filePath) & “_” & FileDateTime(filePath)
stream.Close
End Function
—
3. 設計の勘所:ここを外すと「技術的負債」になる
1. `DoEvents` の慎重な扱い
ファイル書き込み直後にハッシュを計算すると、OSのキャッシュが反映される前に検証が走り、偽の不整合が発生することがある。`DoEvents` を挟むのは定石だが、大規模プロジェクトではループ処理で数秒の「待機」を入れるのが、アーキテクトとしての現場の知恵だ。
2. 「保存前」のハッシュを過信しない
上記コードでは `FileLen` と `FileDateTime` を複合キーにしているが、これはあくまで「簡易チェック」だ。真に厳格な環境であれば、Windows標準の `certutil -hashfile` をシェル経由で叩き、SHA256ハッシュを文字列として取得するアプローチを推奨する。VBAから `WScript.Shell` で呼び出し、標準出力をキャプチャすれば、Python並みの検証精度を担保できる。
3. ベースライン設定との分離
プロジェクトの「ベースライン設定」と「ファイル保存」は、絶対に同一モジュールで実行してはならない。保存が失敗した状態でベースラインが書き換われば、ロールバック不能なデータ汚染を引き起こす。
「保存の完全性検証」→「整合性確認」→「ベースライン更新」というトランザクション順序を厳守せよ。
—
最後に:エンジニアとしての矜持
VBAは「簡易的なツールを作るための言語」と侮られがちだが、大規模なProject管理において、それは「組織の資産を守る最後の防波堤」である。
今回紹介したチェックサム検証は、一見手間がかかるように思えるかもしれない。しかし、プロジェクトの終盤でバイナリ破損により数ヶ月分の進捗が消し飛ぶ悲劇を経験した者なら、この「わずかなコード」がどれほどの価値を持つか理解できるはずだ。
堅牢な設計とは、エラーが起きないことではない。「エラーが起きた瞬間にそれを検知し、被害を最小化できる設計」のことである。諸君のプロジェクトが、常に健全であることを祈る。
