【入門編】実務中級:期限(Deadline)制約とASAP制約の二重設定による進捗遅延検知 – Project VBA解析バイブル

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

「期限」と「計算」の乖離を見抜く。MS Project VBAで実現する、進捗遅延の自動検知アルゴリズム

こんにちは。プロジェクトの複雑なパズルを、コードという名の糸で解き明かしていくエンジニアの皆さん。

マクロの記録機能を使って、「ボタンを押せば何かが動く」という段階を卒業し、「プロジェクトの状況を判断して、自律的に動くシステム」を作りたい……。そう願うようになった時、あなたは真の自動化エンジニアへの入り口に立っています。

今日、皆さんに伝授するのは、Microsoft Project VBAにおける「スケジュールの真実」を暴くテクニックです。

単に「タスクが遅れているか」を見るのではありません。「エンジンの計算(ASAP)」と「人間が設定した理想(Deadline)」の間に生じた「ズレ」を、VBAで自動的に検知する方法です。ここをマスターすれば、あなたの作るツールは「単なる記録係」から「頼れる副操縦士(コ・パイロット)」へと進化します。

1. なぜ「制約」を使い分ける必要があるのか?

まず、MS Projectの心臓部である「スケジューリング・エンジン」の仕組みを理解しましょう。

多くの初心者が陥る罠があります。それは、「絶対にこの日に終わらせたい!」という意思表示を、すべて「制約(Constraint)」として入力してしまうことです。

「硬い制約」の危険性

例えば、タスクに「完了後指定日(Finish No Later Than)」という制約をかけるとどうなるでしょうか?
エンジンは、その日付を守るために、前後のタスクとの論理的な繋がり(依存関係)を無視して、無理やりスケジュールを動かそうとします。これは「クリティカルパス」を破壊し、プロジェクト全体の整合性を失わせる、非常に危険な行為です。

「柔らかい制約」としてのDeadline

そこで登場するのが `Deadline`(期限)プロパティ です。
これは、スケジュール計算自体には一切干渉しません。タスクはあくまで「ASAP(なるべく早く)」の原則に従って、依存関係に基づいて計算されます。

しかし、人間が「この日までに終わっていないとマズい」という目標値を `Deadline` に設定しておけば、計算結果(Finish)が目標(Deadline)を超えた瞬間に、視覚的な警告(赤いアイコン)が出るようになります。

今日のテーマの核心はここです:
> 「エンジンが計算した現実(ASAP)」 > 「人間が設定した理想(Deadline)」

この不等式が成立した瞬間を、VBAでスマートに検知しましょう。

2. 実装の設計図:ロジックの構造

コードを書く前に、頭の中で「アルゴリズム」を組み立てます。いきなり書き始めると、オブジェクトのライフサイクルに振り回されます。

1. 巡回(Loop): プロジェクト内のすべてのタスクを一つずつ見ていく。
2. 除外(Filter): 空白の行や、サマリータスク(親タスク)など、チェック不要なものを飛ばす。
3. 判定(Condition):

  • `Deadline` が設定されているか?
  • `Finish`(計算上の終了日)が `Deadline`(期限)を過ぎているか?

4. アクション(Action): 遅延しているタスクを特定し、色を変える、あるいはログに記録する。

3. 魂を込めたコード:遅延検知エンジン

それでは、実際に現場で使えるレベルのコードを見ていきましょう。単なるサンプルではなく、エラーハンドリングと実用性を考慮した構成にしています。

Option Explicit

''' <summary>
''' Deadlineプロパティと計算上の終了日を比較し、
''' 期限を逸脱しているタスクを特定してハイライトする。
''' </summary>
Sub DetectDeadlineViolations()
    Dim t As Task
    Dim delayCount As Integer
    Dim targetProject As Project
    
    ' 現在アクティブなプロジェクトをセット
    Set targetProject = ActiveProject
    delayCount = 0
    
    ' 画面更新を停止してパフォーマンスを向上(大量タスク対策)
    Application.ScreenUpdating = False
    
    Debug.Print "--- 遅延検知プロセス開始: " & Now & " ---"

    ' プロジェクト内の全タスクをループ
    For Each t In targetProject.Tasks
        
        ' 1. タスクが存在しない(空白行)場合はスキップ
        If t Is Nothing Then GoTo NextTask
        
        ' 2. サマリータスク(親タスク)は計算結果が自動生成されるため、
        '    個別の進捗管理対象外とする場合はスキップ(運用に合わせて変更可)
        If t.Summary Then GoTo NextTask
        
        ' 3. Deadlineが設定されているかチェック
        '    MS ProjectではDeadlineが未設定の場合、内部的に非常に古い日付が入ることがあるため注意
        '    ここでは、Deadlineが実質的に設定されているか(0でないか)を確認
        If t.Deadline <> "00:00:00" Then
            
            ' 4. 【核心部】計算上の終了日(Finish)が、期限(Deadline)を超えているか判定
            If t.Finish > t.Deadline Then
                
                ' 遅延しているタスクへのアクション
                delayCount = delayCount + 1
                
                ' 見やすくするために、タスク名をイミディエイトウィンドウに出力
                Debug.Print "【警告】遅延検知: " & t.Name & _
                            " (終了予定: " & t.Finish & " / 期限: " & t.Deadline & ")"
                
                ' セルに色を塗る(視覚的なアラート)
                ' TextColorを使うことで、見た目のインパクトを強める
                t.TextBefore = "⚠️" ' タスク名の前に警告マークを付与
                t.Start = t.Start     ' (おまじない:プロパティへのアクセスを安定させる)
                
                ' 背景色を赤っぽく変更(エンジニア的な演出)
                ' ※実際には書式設定プロパティを使用
                t.FontColor = pjRed
                
            End If
        End If

NextTask:
    Next t

    ' 画面更新を再開
    Application.ScreenUpdating = True
    
    ' 結果の報告
    If delayCount > 0 Then
        MsgBox "検知完了: " & delayCount & " 件のタスクが期限を逸脱しています。" & vbCrLf & _
               "詳細はイミディエイトウィンドウを確認してください。", vbExclamation, "遅延アラート"
    Else
        MsgBox "全てのタスクは期限内に収まっています。素晴らしい!", vbInformation, "チェック完了"
    End If
    
    Debug.Print "--- プロセス終了 ---"
End Sub

4. ここをクリアすれば、基本はバッチリですよ

このコードを動かす際、あるいは応用する際に、皆さんが躓きやすい「落とし穴」が3つあります。ここを理解しているかどうかが、初級者と中級者の分かれ目です。

① 「未設定のDeadline」の正体

MS ProjectのVBAにおいて、`Deadline` プロパティは、設定されていない場合に「0(1899年12月30日)」のような値として扱われることがあります。
コード内で `If t.Deadline <> “00:00:00” Then` としているのは、この「空っぽの期限」を判定するためです。これを忘れると、「期限を設定していない全てのタスクが、期限切れとして誤検知される」という大惨事が起きます。

② 計算モード(Calculation Mode)の罠

MS Projectには「自動計算」と「手動計算」があります。
もしプロジェクトの設定が「手動計算」になっていると、依存関係を変更しても `t.Finish` が更新されません。VBAで判定を行う直前に、必ずプロジェクトが自動計算モードであることを確認するか、コード内で `targetProject.Calculation = pjCalculationAutomatic` を実行するようにしましょう。

③ オブジェクトの「Nothing」チェック

`For Each t In targetProject.Tasks` でループを回すとき、プロジェクトの行の途中に空白がある場合、`t` は `Nothing` になります。これに対して `.Finish` などのプロパティを読み取ろうとすると、「実行時エラー ’91’: オブジェクト変数または With ブロック変数が設定されていません」という、最も見慣れた、しかし最も厄介なエラーに遭遇します。
必ず `If Not t Is Nothing Then` (または `If t Is Nothing Then GoTo NextTask`)でガードを固める癖をつけてください。

最後に:エンジニアとしての視点

今回学んだ手法は、単なる「遅延チェック」ではありません。
「システムの論理(ASAP)」と「ビジネスの要求(Deadline)」の間に生じる摩擦を、プログラムによって可視化する技術です。

自動化の真価は、人間が「気づかなければならないこと」を、プログラムが「気づかせてくれること」にあります。

このコードをベースに、例えば「遅延しているタスクをメールでプロジェクトマネージャーに飛ばす」といった拡張も可能です。一歩ずつ、コードに魂を込めていってください。

応援していますよ。次はもっと複雑な、リソース平準化の自動制御に挑戦してみましょう。

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