MS Project VBAの「神」になる:保存プロセスを制御する最強のガードロジック
プロジェクト管理において、最も恐ろしいのは「不完全なデータが正として保存されること」だ。MS Projectは柔軟だが、それゆえに現場の担当者が未完了タスクを放置したままファイルを閉じ、プロジェクトの進捗が虚構化するケースが後を絶たない。
多くの初心者は「保存ボタンを押した後にメッセージを出す」という安易な設計に逃げる。だが、それは「保存のキャンセル」ができないという致命的な欠陥を抱えている。
真のアーキテクトは、保存というイベントをアプリケーションのライフサイクル内で確実にフックし、ビジネスロジックに適合しない限り、物理的なストレージへの書き込みを物理的に遮断する。今回は、その「ガードロジック」の実装術を伝授する。
—
なぜ「BeforeSave」をフックするのか
標準の保存ボタンを上書きしようとして、マクロボタンを配置するだけでは不十分だ。ユーザーはショートカット(Ctrl+S)や、ファイルメニューの「保存」を容赦なく使ってくる。
ここで重要になるのが、MS Project VBAにおける`ProjectBeforeSave`イベントだ。これは、保存動作が実行される直前に割り込む唯一無二の門番である。
—
堅牢なガードロジックの実装(プロダクションコード)
以下のコードを、`ThisProject` モジュールに配置せよ。
‘ ———————————————————
‘ Project: ProjectGuard.Global
‘ Description: 未完了タスクが存在する場合の保存キャンセル処理
‘ ———————————————————
Private Sub Project_BeforeSave(ByVal pj As Project)
Dim t As Task
Dim isInvalid As Boolean
‘ 進行中のプロジェクトにおいて、終了していないタスクをチェック
‘ ここでは「完了率が100%ではないタスク」を「未完了」と定義
For Each t In pj.Tasks
If Not t Is Nothing Then
‘ サマリータスクを除外し、実タスクのみを判定するのが肝
If Not t.Summary Then
If t.PercentComplete < 100 Then
isInvalid = True
Exit For
End If
End If
End If
Next t
' ガードロジック:条件を満たさない場合は保存を中断
If isInvalid Then
MsgBox "【警告】未完了のタスクが存在します。" & vbCrLf & _
"全てのタスクが完了するまで保存は許可されません。", vbCritical, "保存の中断"
' 【重要】キャンセルを明示することで、物理的な保存処理を完全に遮断する
' Projectのイベントモデルにおいて、pj.Saved = False を制御するよりも
' 確実な挙動を示す
Err.Raise Number:=vbObjectError + 513, Description:="保存ルール違反"
End If
End Sub
実装のポイント
- `Err.Raise` の活用: 単なるメッセージボックス表示では、ユーザーは「無視して保存」できてしまう。あえてランタイムエラーを発生させることで、Project側の保存プロセスを強制的に例外終了させ、データの書き込みを未然に防ぐ。
- サマリータスクの除外: `t.Summary` を判定条件に入れているか否かで、ツールの質が問われる。サマリータスクは子タスクの集計結果であり、実作業単位ではないため、判定対象から外すのがセオリーだ。
—
運用上の注意点とアーキテクトの矜持
このコードを導入する際に、忘れてはならないリスクがある。
1. 「強制終了」の副作用: `Err.Raise` で保存を止めた場合、ユーザーにはエラーメッセージが表示される。これを「親切なエラーハンドリング」と捉えるか、「不親切なツール」と捉えるかは、UIメッセージの練り込み次第だ。ユーザーに「なぜ保存できないのか」を明記せよ。
2. ベースラインとの整合性: 実務では「保存させない」だけでなく、「ベースラインが設定されていない場合は警告する」といったビジネスルールを組み合わせるケースが多い。`pj.BaselineSavedDate` を参照すれば、プロジェクトの健全性をより多角的に監視できる。
3. データベース連携(Project Server/Online): もし貴方がPWA(Project Web App)環境で運用しているなら、ローカルの保存キャンセルはPWAへのパブリッシュ動作と噛み合わない場合がある。その場合は、`ProjectBeforePublish` イベントも併せてフックする設計が必要になる。
—
まとめ:ツールは「強制力」ではなく「指針」であれ
今回紹介したコードは、言わば「プロジェクトの門番」だ。しかし、ただ保存を止めるだけのツールはユーザーの反感を買う。
- 未完了タスクがどこにあるのか?
- どのタスクを完了させれば保存できるのか?
これらを即座に特定できる「タスクサマリー機能」を別途作成し、保存キャンセルとセットで提供すること。それが、業務自動化エンジニアとしての「優しさ」であり、真の生産性向上に繋がる唯一の道だ。
システムは常に「壊れにくい」のではなく「正しく導く」ものであるべきだ。このロジックを貴方のプロジェクトに組み込み、混沌とした現場に秩序をもたらしてほしい。
