Project VBAの深淵:依存関係を「強制固定」する真の設計思想
世の中の多くのプロジェクト管理者は、Projectの「依存関係(FS: Finish-to-Start)」機能に頼り切りだ。しかし、実務の現場では「先行タスクが終わった瞬間、後続タスクを翌営業日に強制固定したい」「休日やバッファを挟んで自動調整させたい」といった、MS Projectの標準ロジックでは制御しきれない「ビジネスルール」が存在する。
標準機能の甘い自動計算に身を委ねると、ふとした操作でスケジュールが崩壊する。今日我々が実装するのは、MS Projectの計算エンジンをハックし、ビジネスルールを強制適用させるための「堅牢な制御ロジック」だ。
—
1. なぜ「標準の依存関係」だけでは不十分なのか
MS Projectの標準依存関係は、あくまで「制約(Constraint)」に基づく計算だ。しかし、タスクの移動やリソースの付け替えで、意図しない「開始日の自動再計算」が走り、プロジェクト全体がドミノ倒しになる経験はないだろうか?
我々が求めるのは、以下の要件を満たす「強制固定ロジック」だ。
- トリガーの明確化: 先行タスクの完了(%完了 = 100%)をトリガーにする。
- 計算の隔離: 標準の自動スケジュール計算に任せず、VBAで確実に日付を書き込む。
- 不整合の検知: 循環参照や物理的に不可能なスケジュールをエラーとして弾く。
—
2. 堅牢な実装設計のポイント
単に日付を代入するだけのコードは素人の仕事だ。プロフェッショナルは以下の3点を必ず担保する。
1. 計算モードの制御: `Application.Calculation` を適切に管理し、意図せぬ連鎖計算を防ぐ。
2. 型安全と例外処理: `Task` オブジェクトが存在するか、先行タスクが正しいかを確認する。
3. イベントハンドラとの距離: `Project_Change` イベントに重い処理を直接書かない。分離されたモジュールで制御する。
—
3. 実践:依存関係自動固定ロジック
以下は、先行タスクが完了した際に、後続タスクの開始日を「先行終了日の翌日」に強制固定するプロダクションコードの雛形である。
‘ プロジェクトのタスク管理を制御するメインモジュール
Option Explicit
Public Sub ForceSyncFollowUpTask(ByVal predecessorID As Integer, ByVal successorID As Integer)
Dim proj As Project
Dim predTask As Task
Dim succTask As Task
Set proj = ActiveProject
‘ オブジェクトの存在確認(Null参照を防ぐ鉄則)
On Error Resume Next
Set predTask = proj.Tasks(predecessorID)
Set succTask = proj.Tasks(successorID)
On Error GoTo 0
If predTask Is Nothing Or succTask Is Nothing Then
MsgBox “タスクIDが無効です。”, vbCritical
Exit Sub
End If
‘ ビジネスルール:先行が100%完了している場合のみ実行
If predTask.PercentComplete = 100 Then
‘ 依存関係を「開始日固定」に強制上書き
‘ 手動/自動スケジュールを問わず、日付を物理的に押し込む
succTask.Start = predTask.Finish + 1
‘ 制約タイプを「開始日指定」に変更し、計算エンジンによる移動を防ぐ
succTask.ConstraintType = pjMustStartOn
succTask.ConstraintDate = predTask.Finish + 1
Debug.Print “タスク ” & successorID & ” を強制同期しました。”
End If
End Sub
—
4. 運用上の注意点と「伝説」の知見
この実装を行う際、以下の点に注意しなければ、現場で「動かない」「重い」という苦情が飛んでくることになる。
① 大規模プロジェクトでのパフォーマンス
タスク数が数千を超える場合、`Application.Calculation` をループごとに実行させるのは自殺行為だ。処理の開始時に計算モードを `pjManual` に変更し、終了時に `pjAutomatic` に戻すことで、計算のオーバーヘッドを劇的に削減できる。
② データベース・外部ファイル連携の罠
外部のExcelやSQL Serverからタスク情報を読み込んでいる場合、VBAでの書き込みと外部読み込みのタイミングが競合し、いわゆる「ゴースト更新」が発生する。必ず「プロジェクトの保存前(BeforeSave)」や「計算終了後」のイベントで整合性をチェックする二重管理体制を敷くこと。
③ 保守性の極意
このロジックを「標準モジュール」に閉じ込めておくのは悪手だ。クラスモジュールを作成し、`Task`オブジェクトをラップした「ビジネスルール制御クラス」を設計せよ。そうすることで、将来的に「特定のタスクタイプのみに適用する」「祝日を考慮する」といった拡張に、メインの業務ロジックを触らずに対応できる。
—
結論
ツールを自動化するのではない。「プロジェクトの制約条件そのものをコードで定義する」のだ。
MS ProjectをただのGUIツールとして使う時代は終わった。VBAという武器を手に、不確実なプロジェクト環境を確実な「決定論的システム」へと変貌させろ。
君のコードが、プロジェクトを泥沼から救う唯一の砦になることを期待している。
