【テクニカル・上級編】ALAP制約を活用した「納期逆算型」スケジュール自動生成ツールの構築 – Project VBA解析バイブル

スポンサーリンク

【Project VBA】ALAP制約による「納期逆算型」スケジュールエンジンの深淵

VBAを単なる「事務作業の自動化ツール」と見なすのは、アーキテクトとしては三流だ。Project VBA、特にMS Projectのオブジェクトモデルを掌握するということは、メモリ空間の端から端まで、スケジュールの制約という名の「論理的鎖」を制御することに他ならない。

今回は、納期(Deadline)を起点に全タスクを配置するALAP(As Late As Possible:可能な限り遅く)制約を用いたスケジュールエンジンの核心に迫る。

—

1. なぜ「ALAP」は鬼門なのか

多くの初学者は、`Task.Start`に直接値を代入してスケジュールを組もうとする。これは大いなる過ちだ。MS Projectの計算エンジンは、一度手動で値を書き込むと「制約の固定(Constraint Type)」が自動的に発生し、後続の依存関係による動的な再計算を阻害する。

ALAP制約の真髄は、「終了日を固定し、依存関係(Predecessors)を逆流させて開始日を自動算出させる」ことにある。これをVBAで制御するには、`pjConstraintALAP`をプロパティとして適用するだけでなく、プロジェクトの計算モードと同期させなければならない。

—

2. 実装の設計思想:メモリ管理と安全なAPI呼び出し

VBAで大規模なスケジュールを扱う際、最も避けなければならないのは、MS Projectのオブジェクトモデルが生成する「一時的な参照の残留」によるメモリリークだ。`Set obj = Nothing`を繰り返すだけでは不十分。COMオブジェクトのライフサイクルを意識せよ。

ALAPスケジュール生成エンジン(コアロジック)

‘ プロジェクトのタスクに対してALAP制約を適用し、納期を起点に逆算する
Public Sub ApplyALAPConstraint(ByRef proj As Project, ByVal targetTaskID As Long, ByVal deadLineDate As Date)
Dim tsk As Task
Set tsk = proj.Tasks(targetTaskID)

‘ 1. 制約をALAPに設定(これにより自動的に期間計算が逆算モードに入る)
tsk.ConstraintType = pjConstraintALAP

‘ 2. 納期を締め切りとして設定(Deadlineプロパティは計算を固定しないため重要)
tsk.Deadline = deadLineDate

‘ 3. パフォーマンス最適化:再計算のトリガーを抑制
‘ 大量タスク更新時は Calculation プロパティを一旦手動に切り替えるのが鉄則
Dim originalCalcMode As PjCalculation
originalCalcMode = Application.Calculation
Application.Calculation = pjManual

‘ — ここで依存関係のチェックや調整を行う —

‘ 4. 再計算を強制実行し、ALAPの論理を反映させる
Application.Calculation = originalCalcMode
Application.CalculateProject

‘ メモリの明示的解放(オブジェクトの参照カウントを意識)
Set tsk = Nothing
End Sub

—

3. レガシー環境を生き抜くための極限の知見

Windows APIによるタスクの同期

MS Projectの計算エンジンはバックグラウンドで非同期に動くことがある。特に大量のタスクを更新する際、`Application.CalculateProject`が完了する前に次の処理へ移ると、計算結果が不整合を起こす。

これを防ぐには、Windows API `Sleep` を利用し、計算完了まで待機するポーリング処理を実装するのが、現場のエンジニアが辿り着く「泥臭いが確実な」解法だ。

If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

‘ 計算完了まで待機するセーフティネット
Public Sub WaitUntilCalculated(ByVal app As MSProject.Application)
Do While app.IsCalculating
Sleep 100 ‘ 100msの待機でCPU負荷を抑えつつ待機
DoEvents
Loop
End Sub

—

4. チーフアーキテクトからの忠告:保守性を殺すな

このツールを組織に導入する際、最も注意すべきは「MS ProjectのGUI上でユーザーが値を弄る」リスクだ。VBAで制御したロジックを、ユーザーが手動入力で破壊する事態を防ぐには、以下の実装を推奨する。

  • カスタムフィールドの活用: ALAP制御対象のタスクには、`Flag1`などのカスタムフィールドに`True`を立て、手動変更を検知するイベントプロシージャ(`Project_BeforeTaskChange`)を実装せよ。
  • 整合性チェックの自動化: ロジック実行後、必ず`Task.ConstraintDate`と`Task.Start`の差分を検証するログを出力させること。

結びに代えて

VBAでスケジュールエンジンを組むということは、単なるコード記述ではない。MS Projectという巨大なCOMサーバーの内部ロジックを、あなたのコードで「調教」する行為だ。

ALAP制約は、納期という「絶対的な終端」から逆算する。これこそが、不確実なプロジェクトを制御下に置くための、もっとも静かで、もっとも強力な武器となる。

コードに魂を込めよ。その一行が、明日から現場の誰かの「残業」を救うかもしれないのだから。

タイトルとURLをコピーしました