【Project VBA極意】保存イベントを掌握せよ:変更監査ログを確実に残す設計思想
プロジェクト管理において、最も恐ろしいのは「いつの間にかデータが書き換わっている」ことだ。特にMS Projectの運用において、誰が、いつ、どのような意図で保存したのかという事実は、後のトラブルシューティングにおける生命線となる。
今回は、Project VBAのイベント駆動モデルを正しく理解し、現場で耐えうる堅牢な「監査ログ出力機構」を構築する手法を伝授する。
—
1. なぜ「BeforeSave」イベントなのか
VBAでプロジェクトのライフサイクルを制御する場合、重要なのはイベントの「タイミング」だ。`ProjectBeforeSave` イベントは、ファイルがディスクに書き込まれる直前に発火する。
ここで重要なのは、「保存が確定する前にログを吐く」こと。もし書き込みエラーが発生した場合、ログだけが残り実体がないという不整合を防ぐために、エラーハンドリングを厳密に行う必要がある。
2. 堅牢な設計のための3つの鉄則
1. I/Oの局所化: ファイルI/Oは最も低速で不安定な処理だ。監査ログは追記型(Append)で扱い、一度開いたストリームは確実に閉じる。
2. イベントの再帰防止: 保存処理中にログ出力で再度保存を呼ぶような、無限ループの設計ミスを徹底的に排除する。
3. 環境依存の排除: ログファイルのパスはハードコードせず、プロジェクトのプロパティや環境変数から動的に取得する設計にする。
—
3. 実践:プロジェクト監査ログ実装コード
以下のコードを `ThisProject` モジュールに配置せよ。
‘ ———————————————————
‘ Module: ThisProject
‘ 監査ログ出力機能を実装するためのイベントハンドラ
‘ ———————————————————
Private Sub Project_BeforeSave(ByVal pj As Project, ByVal SaveAsUi As Boolean, Cancel As Boolean)
On Error GoTo ErrorHandler
‘ ログファイルの保存先(ネットワークドライブ等のパスを指定)
Dim logPath As String
logPath = “C:\AuditLogs\ProjectAudit.csv”
‘ ログ出力用のファイル番号を取得
Dim fileNum As Integer
fileNum = FreeFile
‘ 追記モードでオープン
Open logPath For Append As #fileNum
‘ 監査データの書き出し (日時, ユーザー名, ファイル名)
‘ 環境変数のUserNameを取得することで、誰のPCで保存されたかを追跡
Print #fileNum, Format(Now, “yyyy-mm-dd hh:nn:ss”) & “,” & _
Environ(“UserName”) & “,” & _
pj.Name & “,” & _
IIf(SaveAsUi, “SaveAs”, “Save”)
Close #fileNum
Exit Sub
ErrorHandler:
‘ ログ書き込み失敗でプロジェクト自体を止めるべきか、ログを諦めるかは
‘ ポリシー次第。ここではエラーを通知しつつ処理を続行する
MsgBox “監査ログの記録に失敗しました: ” & Err.Description, vbCritical
If fileNum > 0 Then Close #fileNum
End Sub
—
4. プロダクション環境における懸念と対策
ファイルI/Oの衝突
複数ユーザーが同一のネットワークパスに書き込む環境では、`Open … For Append` が排他制御で競合する可能性がある。より高信頼性を求めるなら、`FileSystemObject (FSO)` を使用し、`.OpenTextFile` メソッドでストリームを細かく制御するか、あるいはログを一時的なキューとしてメモリに溜め込み、終了時にバッチ処理する設計が必要だ。
「保存しない」という選択
このイベントは「保存ボタンが押された時」に発火する。しかし、ユーザーがタスクを削除した後に「保存せずに閉じる」ケースまでは追跡できない。これを補完するには、`ProjectBeforeClose` イベントにも同様のロジックを仕込み、`pj.Saved` プロパティをチェックして「変更があるのに保存されずに閉じられた」事象をログに残すのが、真にプロフェッショナルな設計というものだ。
最後に:エンジニアとしての矜持
VBAはレガシーと言われることもあるが、MS Projectの内部オブジェクトに直接アクセスできる唯一の武器だ。この「保存イベントのフック」は、単なる機能追加ではない。組織のプロジェクト管理における「ガバナンス」をコードで担保する行為である。
このコードをコピー&ペーストするだけでなく、なぜこの場所に書くのか、なぜエラーハンドリングが必要なのかを咀嚼してほしい。それが君のプロジェクトを成功へと導く第一歩となる。
