Project VBAの深淵:BeforeSaveイベントで「不整合なプロジェクト」を物理的に排除する
プロジェクトマネジメントにおいて、最も恐ろしいのは「データが汚染されたまま保存されること」です。現場のメンバーが適当に入力した工数、放置されたマイルストーン、空欄の必須フィールド。これらが蓄積されたプロジェクトファイルは、もはや管理ツールではなく、ただの負債です。
今日は、Project VBAの最重要イベントの一つである `ProjectBeforeSave` を掌握し、プロジェクトの「品質」を強制的に担保する堅牢な実装術を伝授します。
—
なぜ「保存時」なのか:防御的プログラミングの鉄則
多くのエンジニアは、ボタンを押した時にバリデーションを行います。しかし、人間は必ずミスをします。「保存」という最後の砦でチェックを行わない限り、不整合なデータはサーバーや共有フォルダへと蔓延します。
`ProjectBeforeSave` イベントは、ファイルの書き込み処理が実行される直前に割り込みをかけます。ここでエラー検知をすれば、不完全なデータが外部に出ることを物理的に遮断できるのです。
—
堅牢な設計:Class Moduleによる「イベントの局所化」
多くの初心者が `ThisProject` モジュールに直接コードを書き込みますが、これは保守性の観点から見れば悪手です。プロジェクトが大規模化し、イベントが増えた瞬間にスパゲッティコードと化すからです。
ここでは、「イベントハンドラ専用のクラスモジュール」を作成し、`Application` オブジェクトを監視する設計を採用します。
実装ステップ
1. クラスモジュールを作成する(名前: `clsAppEvent`)
このクラスが、プロジェクト全体の動きを監視する「番人」となります。
‘ クラスモジュール: clsAppEvent
Public WithEvents App As MSProject.Application
Private Sub App_ProjectBeforeSave(ByVal pj As Project, ByVal SaveAs As Boolean, Cancel As Boolean)
‘ 整合性チェック関数を呼び出す
If Not ValidateProjectData(pj) Then
‘ チェックが通らなければ保存をキャンセルする
MsgBox “データ整合性エラー: 必須項目の確認が必要です。”, vbCritical, “保存中止”
Cancel = True
End If
End Sub
2. チェックロジックを分離する(標準モジュール: `modValidator`)
バリデーションのロジックは、イベントハンドラから切り離して独立させます。これにより、将来的なルールの変更(例:工数の計算ロジック変更)にも柔軟に対応可能です。
‘ 標準モジュール: modValidator
Public Function ValidateProjectData(pj As Project) As Boolean
Dim t As Task
ValidateProjectData = True ‘ 初期値は真
‘ 全タスクを走査
For Each t In pj.Tasks
If Not t Is Nothing Then
‘ 例: 「名前」が空、または「実績工数」が未入力のタスクを検知
If t.Name = “” Or t.ActualWork = 0 Then
ValidateProjectData = False
Exit Function
End If
End If
Next t
End Function
3. イベントを起動する(標準モジュール: `modInitializer`)
プロジェクトを開いた瞬間に、この監視システムをアクティブにします。
‘ 標準モジュール: modInitializer
Dim myAppEvent As clsAppEvent
Sub Auto_Open()
‘ Project起動時に監視を開始
Set myAppEvent = New clsAppEvent
Set myAppEvent.App = MSProject.Application
End Sub
—
現場で差がつく3つの注意点
1. ユーザーへのフィードバックを設計せよ
単に `Cancel = True` とするだけでは、ユーザーは「なぜ保存できないのか」を理解できず混乱します。エラー箇所を特定し、どのタスクが原因かをメッセージボックスで明示するか、あるいは対象タスクを選択状態にする等のUIフィードバックを組み込んでください。
2. パフォーマンスの罠を避ける
`ProjectBeforeSave` は頻繁に実行されます。タスクが数千件規模になると、ループ処理だけで保存に数秒のラグが生じます。
- `ActiveProject.Tasks` の全走査は、変更があったタスクのみをフィルタリングするなどの工夫を行い、計算コストを最小化してください。
3. データベース連携時の「整合性」
もしこのProjectファイルをDBへエクスポートする運用を行っているなら、このイベント内で「DBのスキーマとProjectのフィールド定義が一致しているか」までチェックするフックを仕込んでください。データの不整合がDBに書き込まれた後のリカバリコストは、保存を止めるコストの100倍以上です。
—
最後に:エンジニアとしての矜持
「自動化」とは、ただ楽をすることではありません。「ミスが起きる余地をシステム的に排除し、人間が本来やるべき価値ある作業に集中させること」です。
今回紹介したイベントハンドラの実装は、あなたのプロジェクト管理を「属人的な注意」から「システム的な保証」へと昇華させます。ぜひ、あなたの現場でこの「守りのコード」を走らせてみてください。
技術は、使う者の意志次第で、ただのツールにも、最強の防壁にもなります。健闘を祈ります。
