Project VBAの深淵:依存関係の再計算と「時間」の支配
プロジェクト管理において、開始日の変更は「悪夢」だ。数千行のWBSが連鎖的に崩壊し、手作業での修正はエンジニアとしての矜持が許さない。
Project VBA(Microsoft Project Object Model)を操作する際、多くの者は単に `Task.Start` を書き換えるだけで満足する。だが、それは素人の所業だ。依存関係(Predecessors)が複雑に絡み合う巨大プロジェクトにおいて、単純な代入は制約条件(Constraint)の衝突を生み、計算エンジンをスタックさせる。
真のアーキテクトは、オブジェクトのライフサイクルを制御し、計算ロジックを最適化する。本稿では、プロジェクト開始日変更に伴う依存関係の再構築を、理論と実装の両面から掌握する。
—
1. 依存関係の「鎖」を解き放つ
Projectのタスクにおいて、最も忌むべきは「制約条件(ConstraintType)」の残留だ。手動で日付をいじった結果、`MSO_CONSTRAINT_START_NO_EARLIER_THAN` 等がこびりつき、自動計算を阻害しているケースが後を絶たない。
依存関係を再計算する前に、まず全タスクの制約を「可能な限り早く(As Soon As Possible)」へリセットする。これが全ての出発点だ。
‘ 制約条件をクリアし、依存関係に基づく自動計算を強制する
Public Sub ResetConstraintsAndSchedule(ByRef proj As Project)
Dim t As Task
‘ プロジェクト全体を計算モードに強制
proj.Calculation = pjManual
For Each t In proj.Tasks
If Not t Is Nothing Then
‘ 制約をクリア(ASAPに設定)
t.ConstraintType = pjAsSoonAsPossible
‘ 手動スケジュールを解除
t.Manual = False
End If
Next t
‘ 計算を再実行
proj.Calculation = pjAutomatic
proj.Recalculate
End Sub
2. メモリとパフォーマンスの極限制御
数万行規模のWBSを扱う際、`For Each` ループはメモリリークやオブジェクトの断片化を招くリスクがある。特に、ProjectのオブジェクトモデルはCOM層を介するため、オブジェクト参照を保持したままループを回すと、ガベージコレクションが適切に機能しないことがある。
シニアエンジニアは、`Nothing` への解放を怠らない。また、画面更新を抑制(`Application.ScreenUpdating = False`)するのは基本だが、さらに一歩進んで、計算エンジンとの同期を意図的に切断・再接続することで、パフォーマンスを劇的に向上させる。
3. 実装の核心:開始日変更ロジック
開始日をシフトする際、単に「プロジェクト開始日」を変更するだけでは不十分だ。既存のタスクの相対的なタイムラインを維持しつつ、依存関係の論理構造を維持する。
‘ プロジェクト開始日をシフトし、依存関係を再構築する
Public Sub ShiftProjectStart(ByVal newStartDate As Date)
Dim proj As Project
Set proj = Application.ActiveProject
‘ 1. 計算の一時停止(オーバーヘッド削減)
Application.ScreenUpdating = False
proj.Calculation = pjManual
‘ 2. プロジェクト全体のプロパティ更新
proj.ProjectStart = newStartDate
‘ 3. 全タスクの制約リセット(前述の関数を活用)
ResetConstraintsAndSchedule proj
‘ 4. オブジェクトの明示的解放と計算再開
Set proj = Nothing
Application.ScreenUpdating = True
‘ 非同期計算を考慮した再計算
Application.ActiveProject.Recalculate
MsgBox “スケジュール再構築完了:依存関係の整合性確認済み”, vbInformation
End Sub
4. 伝説のアーキテクトからの忠告
このコードは強力だが、銀の弾丸ではない。以下の点に注意せよ。
- サマリータスクの制約: サマリータスクに直接依存関係が設定されている場合、計算エンジンは非常に気難しい挙動を見せる。WBSの深層で依存関係が「ループ」していないか、`Task.Predecessors` を再帰的にチェックするバリデーターを別途実装することを推奨する。
- Windows APIの介入: 極めて巨大なファイルでメモリ不足が発生する場合、`GlobalMemoryStatusEx` を呼び出し、利用可能な物理メモリを監視しながらタスクをバッチ処理するロジックが必要になる。VBAの限界は、APIの力を借りることで初めて突破できる。
- 永続性: プロジェクトファイルのバージョンによる仕様差異を吸収するため、`proj.Version` を確認し、プロパティのアクセス方法を分岐させるのが、レガシー環境を生き抜く者の知恵だ。
—
自動化とは、単にコードを書くことではない。システムが持つ「論理的な制約」を理解し、それを正しく再構築する「調律」の作業である。貴殿が手掛けるプロジェクトが、この技術によって少しでも無駄な手作業から解放されることを願う。
コードは嘘をつかない。だが、書く者の意志が伴わなければ、ただの文字列に過ぎない。さあ、コンパイルして実行せよ。
