【実務・中級編】【上級者向け】COMアドインを用いた、プロジェクトの「保存」処理に対する強制的なトランザクション制御 – Project VBA解析バイブル

スポンサーリンク

プロジェクトの死を回避せよ:MS Project VBAにおける「原子性」を担保するトランザクション制御の極意

現場のプロジェクトマネージャーや自動化エンジニア諸君。君たちは「保存処理の失敗」という悪夢に直面したことがあるか?

MS Project(MSP)の保存処理は、単純な`FileSave`メソッドではない。大規模なプロジェクトファイルになればなるほど、I/Oのレイテンシやネットワークの瞬断、あるいはアドインによる干渉で、ファイルが半壊した状態で保存されるリスクが常につきまとう。

本稿では、VBA単体では到達不可能な「保存のトランザクション制御」を、COMアドインの視点から実装する極限の設計論を授ける。

1. なぜ「標準の保存」では不十分なのか

通常のVBAコードで`ActiveProject.Save`を実行するだけでは、以下のリスクを制御できない。

  • 非アトミックな書き込み: 保存プロセス中にプロセスがクラッシュした場合、MSPは「部分的に書き込まれたゴミファイル」を残して終了する。
  • 整合性の欠如: 外部データベースや他のアドインと連携している場合、片方の更新だけが成功し、プロジェクトファイルとデータの不整合が発生する。

我々が目指すべきは、「すべてが成功するか、あるいは何も起きなかったことにするか」という、データベーストランザクションのような堅牢性である。

2. アーキテクチャの設計思想:シャドウコピー戦略

「保存に失敗したらロールバックする」という理想をVBAで実現するためには、直接ファイルを上書きするのではなく、以下の手順を踏む必要がある。

1. ステージング: 現在のプロジェクトを「一時的な作業用ファイル」として別名保存する。
2. 検証: 作業用ファイルが正しく保存されたことを確認する。
3. スイッチ: 作業用ファイルを元のファイル名にリネーム(上書き移動)する。
4. クリーンアップ: 成功時は一時ファイルを削除、失敗時は例外をキャッチして元の状態を維持する。

3. 実装:堅牢なトランザクション制御プロシージャ

以下に、実務でそのまま運用可能な、エラーハンドリングを完備した設計を示す。

‘ @brief プロジェクトを安全に保存するためのトランザクション・ラッパー
‘ @param targetProject 保存対象のProjectオブジェクト
‘ @param targetPath 保存先のフルパス
Public Sub SafeSaveProject(ByRef targetProject As Project, ByVal targetPath As String)
Dim tempPath As String
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 一時ファイル名(作業用)の生成
tempPath = targetPath & “.tmp”

On Error GoTo ErrorHandler

‘ 1. ステージング:一時ファイルへ保存
‘ 保存処理が失敗した場合、ここで即座にエラーハンドラへ飛ぶ
targetProject.SaveAs Name:=tempPath

‘ 2. スイッチ:一時ファイルを正式なパスへ移動(上書き)
‘ FileSystemObjectのMoveFileはOSレベルでアトミックに近い動作を行う
fso.MoveFile tempPath, targetPath

Debug.Print “保存完了: ” & targetPath
Exit Sub

ErrorHandler:
‘ 3. ロールバック:一時ファイルが残っていれば削除
If fso.FileExists(tempPath) Then
fso.DeleteFile tempPath
End If

MsgBox “保存プロセスで致命的なエラーが発生しました。データは更新されていません。” & vbCrLf & _
“エラーコード: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “トランザクション失敗”
Err.Clear
End Sub

4. 運用上の極めて重要な注意点

このコードをただコピペするだけでは、真のエンジニアとは言えない。以下の「境界条件」を必ず考慮せよ。

  • 排他制御の罠: プロジェクトが既に他のユーザーによって開かれている場合、`MoveFile`は失敗する。`fso.FileExists`のチェックだけでなく、ファイルがロックされていないかを事前に検証するロジック(`Open … For Output Lock Read Write` を試行する等)を組み込むことが理想だ。
  • COMアドインのライフサイクル: この処理をアドインの`BeforeSave`イベントでフックする場合、`Cancel = True`を設定し、手動で上記の`SafeSaveProject`を回すこと。MSP標準の保存プロセスと競合させてはならない。
  • ログ出力: 失敗時は必ずイベントビューアやログファイルへ「どのタイミングで」「何が原因で」失敗したかを書き出すこと。事後検証できないシステムは、存在しないのと同じだ。

5. 最後に:プロフェッショナルの矜持

ツールを作ることは、誰かの業務の「安全」を預かることだ。
VBAは簡便な言語だが、その裏側にはOSのI/O管理やメモリの制約が深く関わっている。プロジェクトファイルの保存は、システムの心臓部だ。そこを安易なコードで済ませるな。

君たちの書くコードが、明日の誰かの仕事を守る盾となることを期待している。
もし更なる高度なアドイン設計(C# / .NET連携による非同期保存)が必要なら、いつでも扉を叩け。道は用意してある。

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