【入門編】実務中級:制約条件の変更がクリティカルパスに与える影響をVBAで事前シミュレーション – Project VBA解析バイブル

スポンサーリンク
スポンサーリンク

「マクロの記録」の先へ。Project VBAでスケジュール計算エンジンの「予兆」を読み解く

こんにちは。プロジェクトの複雑なネットワークを、コードという名の糸で解き明かしていく、あなたのエンジニア仲間です。

皆さんは、Microsoft Projectを使っていて、こんな不安に襲われたことはありませんか?

「このタスクの制約条件(制約)を『開始日指定』に変えたら、プロジェクト全体の終了日はどれくらい後ろにズレるんだろう?」
「もし、このタスクを『遅延開始(ALAP)』に設定したら、クリティカルパスはどこに移動してしまうのか?」

「マクロの記録」でボタン操作を記録する段階を卒業し、一歩上の「自動化エンジニア」を目指そうとしているあなた。今、あなたが直面しているその「不確実性への不安」こそが、プログラミングで解決すべき最高のテーマです。

今日は、Project VBAの心臓部である「スケジュール計算エンジン」を制御し、変更の影響を事前にシミュレーションする、実務レベルのテクニックを伝授します。ここをクリアすれば、あなたはもう「ただの記録者」ではなく、「プロジェクトの設計者」になれるはずですよ。

1. なぜ「制約条件」の変更は怖いのか?

MS Projectの強みは、タスク間の依存関係(先行・後続)を計算して、自動でスケジュールを組んでくれる「計算エンジン」にあります。

しかし、このエンジンには「制約条件(Constraints)」という強力なルールが存在します。

  • ASAP (As Soon As Possible): できるだけ早く(標準的な状態)。
  • ALAP (As Late As Possible): できるだけ遅く(余裕を最大限使う状態)。
  • Must Start On: 必ずこの日に開始しなければならない(強力な固定)。

これらはスケジュールにおける「錨(いかり)」や「壁」のようなものです。ASAPで動いていたタスクに「Must Start On」という壁を設置した瞬間、そのタスクは周囲のタスクを押し退け、プロジェクト全体の終了日をドミノ倒しのように変化させることがあります。

これを手動で行うと、ミスが発生しやすく、何より「もし間違っていたら?」という恐怖がつきまといます。だからこそ、「実際に変更する前に、計算エンジンに『もしこうなったら?』と問いかけるシミュレーター」が必要なのです。

2. シミュレーションのアルゴリズム(設計図)

いきなりコードを書き始めるのは、設計図なしにビルを建てるようなものです。プロのエンジニアは、まず「ロジックのライフサイクル」を定義します。

今回のシミュレーターが辿るステップは以下の通りです。

1. 現在の状態を記憶する: 現在のプロジェクト終了日と、対象タスクの元の制約条件をメモリに保存しておく。
2. 仮の変更を適用する: ユーザーが試したい新しい制約条件を、対象タスクに適用する。
3. 計算エンジンを強制駆動する: `Project.Calculate` を呼び出し、変更が全体に波及した結果を算出させる。
4. 影響度を測定する: 新しいプロジェクト終了日と、記憶しておいた終了日を比較する。
5. 状態を復元する: ここが最も重要です。 シミュレーションが終わったら、プロジェクトを元の状態に戻さなければなりません。
6. 結果を報告する: ユーザーに「〇日ズレますよ」と優しく通知する。

3. 実践:影響シミュレーション・コード

それでは、魂を込めたコードを見ていきましょう。このコードは、選択しているタスクに対して、制約条件を変更した場合の影響を計算します。

Option Explicit

''' <summary>
''' 選択したタスクの制約条件を変更した場合の、プロジェクト終了日への影響をシミュレーションする
''' </summary>
Sub SimulateConstraintImpact()
    Dim targetTask As Task
    Dim originalFinishDate As Date
    Dim simulatedFinishDate As Date
    Dim originalConstraint As PjConstraintType
    Dim newConstraint As PjConstraintType
    Dim impactDays As Long
    
    ' 1. エラーハンドリングとオブジェクトの取得
    ' 選択されているものがタスクでない場合に備える
    On Error GoTo ErrorHandler
    Set targetTask = ActiveSelection.Tasks(1)
    
    If targetTask Is Nothing Then
        MsgBox "タスクを選択してから実行してください。", vbExclamation
        Exit Sub
    End If

    ' 2. 現在の状態を「記憶」する (Object Lifecycle Management)
    ' プロジェクト全体の終了日と、タスクの現在の制約をバックアップ
    originalFinishDate = Project.FinishDate
    originalConstraint = targetTask.ConstraintType
    
    ' 3. ユーザーに「何を確認したいか」を問いかける
    ' ここでは例として、最も影響が出やすい「Must Start On」への変更をシミュレート
    ' 本来は、ダイアログ等でユーザーに選択させるのが理想的です
    newConstraint = pjMustStartOn
    
    ' 4. 仮の変更を適用
    ' ※ 注意: ここで実際にデータを書き換えます
    targetTask.ConstraintType = newConstraint
    
    ' 5. スケジュール計算エンジンの強制実行
    ' これを呼ばないと、Projectは内部的な再計算を後回しにする場合があります
    Project.Calculate
    
    ' 6. 新しい終了日を取得
    simulatedFinishDate = Project.FinishDate
    
    ' 7. 影響度(差分)の計算
    impactDays = DateDiff("d", originalFinishDate, simulatedFinishDate)
    
    ' 8. 状態の復元 (Rollback)
    ' シミュレーションの結果、データが壊れても元の状態に戻るように必ず実施します
    targetTask.ConstraintType = originalConstraint
    Project.Calculate
    
    ' 9. 結果の通知
    If impactDays > 0 Then
        MsgBox "【警告】制約を変更すると、プロジェクト終了日が " & impactDays & " 日遅延します。" & vbCrLf & _
               "現在の終了日: " & Format(originalFinishDate, "yyyy/mm/dd") & vbCrLf & _
               "予測終了日: " & Format(simulatedFinishDate, "yyyy/mm/dd"), vbCritical, "シミュレーション結果"
    ElseIf impactDays < 0 Then
        MsgBox "【通知】制約を変更すると、プロジェクト終了日が " & Abs(impactDays) & " 日早まる可能性があります。" & vbCrLf & _
               "(※制約による強制的な前倒しの場合)", vbInformation, "シミュレーション結果"
    Else
        MsgBox "【確認】制約を変更しても、プロジェクト全体の終了日には影響しません。", vbInformation, "シミュレーション結果"
    End If

    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

4. プロの視点:陥りやすい罠と回避策

コードを書けるようになったあなたに、現場で役立つ「極限の知見」を授けます。

① `Project.Calculate` の重みを知る

MS Projectは、パフォーマンスを維持するために「計算が必要な時まで計算を遅延させる」という賢い動きをします。しかし、VBAで値を書き換えた直後にその値を読み取ろうとしても、計算が走っていないと「古い値」を返してしまいます。
シミュレーションの直前には、必ず `Project.Calculate` を明示的に呼び出すこと。これが、正確なシミュレーションを行うための鉄則です。

② 「状態の復元(Rollback)」を忘れない

今回のコードで最も重要なのは、変更を適用した後に `targetTask.ConstraintType = originalConstraint` で元に戻している点です。
もし、シミュレーション中にエラーが起きてプログラムが止まってしまったら? プロジェクトは「仮の変更」が適用されたまま、ぐちゃぐちゃになってしまいます。
実務では、さらに高度な手法として、「一度プロジェクト全体を別名で保存(一時保存)し、シミュレーションが終わったらそのファイルを閉じる」という、物理的なバックアップ戦略をとることもあります。

③ オブジェクトの参照エラー

`ActiveSelection.Tasks(1)` は非常に便利ですが、何も選択していない状態で実行するとエラーになります。必ず `If targetTask Is Nothing Then` のようなチェックを入れ、ユーザーに優しくエラーを伝える(=「タスクを選んでね」と言う)ことが、一流のエンジニアの作法です。

最後に:ここをクリアすれば、基本はバッチリです

いかがでしたか?

「マクロの記録」は、単なる操作のコピーです。しかし、今回のように「現在の状態を保持し、仮の変更を行い、計算させ、比較し、元に戻す」という一連のフローをコントロールできるようになれば、あなたはMS Projectを「操作する対象」から「制御するシステム」へと昇華させたことになります。

この「シミュレーション・ロジック」は、制約条件だけでなく、リソースの割り当て変更や、期間の変更など、あらゆる場面に応用可能です。

一歩ずつ、着実に。コードの背後にある「プロジェクトの動き」を感じながら、素晴らしい自動化の世界を楽しんでください。応援していますよ!

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