【入門編】【実務中級】「期限(Deadline)」設定と「終了日固定」制約の併用による、進捗遅延リスクの早期アラートシステム – Project VBA解析バイブル

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

Project VBAを掌握する極限の知見:制約条件の罠を回避し、「期限」でプロジェクトの未来を予兆する

こんにちは。プロジェクトの複雑なパズルを解き明かす、エンジニアの皆さん。
マクロの記録ボタンを押し、生成されたコードを眺めて「ふむふむ、動いているな」と納得するフェーズは、もう卒業しましょう。

今日、皆さんに伝授したいのは、単なる「自動化」ではありません。Microsoft Projectの計算エンジン(Scheduling Engine)の性質を理解し、プロジェクトが破綻する前に「警告」を鳴らす、アーキテクトとしての思考法です。

多くのユーザーが陥る罠があります。それは、「制約条件(Constraints)」を使いすぎて、スケジュール計算の柔軟性を殺してしまうことです。

今回は、制約条件と「期限(Deadline)」を賢く使い分け、遅延リスクを早期に検知する「アラートシステム」の構築方法を解説します。ここをクリアすれば、あなたのProject VBAスキルは、単なる事務作業の自動化から、プロジェクト管理の品質向上ツールへと進化するはずですよ。

1. 知っておくべき「二つの境界線」:制約条件 vs 期限

まず、ここが最も重要な概念的な違いです。ここを誤解すると、せっかく組んだスケジュールが「ガチガチに固まって動かない」という悪夢を見ることになります。

制約条件 (Constraints) — 「命令」

「開始日固定」「終了日固定(Must Finish On)」などは、計算エンジンに対する絶対的な命令です。
エンジンの計算ロジック(先行・後続関係)よりも、この制約が優先されます。

  • リスク: あちこちに「固定」を使いすぎると、一つのタスクが遅れたときに、連鎖的に他のタスクが「計算不能」に陥ったり、無理やり日付がねじ曲がったりして、スケジュールの整合性が崩壊します。

期限 (Deadline) — 「目標」

一方で「期限(Deadline)」は、計算エンジンに対する命令ではなく、「この日までに終わってほしい」という単なるラベル(属性)です。

  • メリット: 期限を設定しても、タスクの計算(Finish Date)は先行・後続関係に従って柔軟に動きます。もし計算結果が期限を過ぎてしまった場合、Projectは「警告(赤い旗)」を出してくれますが、スケジュールそのものを破壊することはありません。

【結論】
プロのアーキテクトは、「制約条件は最小限(基本はASAP:可能な限り早く)に留め、管理の境界線には『期限』を使う」のです。

2. 実装のシナリオ:遅延リスク早期アラートシステム

では、具体的に何を自動化するのか?
今回のゴールは、以下のロジックを持つVBAツールです。

1. 各タスクの「期限(Deadline)」をチェックする。
2. 「計算された終了日(Finish)」が「期限」を過ぎている、あるいは「期限の直前(例:5日以内)」に迫っているタスクを特定する。
3. それらのタスクをリストアップし、視覚的に強調する。

これにより、「期限を過ぎてから気づく」のではなく、「期限に間に合わなくなりそうな予兆」を捉えることができます。

3. 実践:アラート検知エンジンのコード

さあ、コードを書いていきましょう。
「マクロの記録」では決して書けない、オブジェクトの存在確認(Nothingチェック)を含んだ、堅牢なコードです。

Option Explicit

''' <summary>
''' プロジェクト内のタスクをスキャンし、期限切れまたは期限接近のリスクを検知する
''' </summary>
Sub AlertDeadlineRisk()
    Dim t As Task
    Dim warningDays As Integer
    Dim riskCount As Integer
    Dim reportMsg As String
    
    ' --- 設定エリア ---
    ' 期限の何日前から警告を出すか(例:5日前)
    warningDays = 5
    riskCount = 0
    reportMsg = "【遅延リスク検知レポート】" & vbCrLf & vbCrLf
    ' ------------------

    ' プロジェクト内の全タスクをループ
    For Each t In ActiveProject.Tasks
        
        ' 1. 空の行(TaskオブジェクトがNothing)はスキップ
        ' これを忘れると、空行がある場合にエラーで止まってしまいます
        If Not t Is Nothing Then
            
            ' 2. 期限(Deadline)が設定されているか確認
            ' pjDateNotSet は、日付が設定されていない状態を示す定数です
            If t.Deadline <> pjDateNotSet Then
                
                ' 3. リスク判定ロジック
                ' ケースA: すでに期限を過ぎている (Finish > Deadline)
                ' ケースB: 期限の数日以内に終了予定 (Finish + warningDays >= Deadline)
                
                If t.Finish > t.Deadline Then
                    ' 【致命的】期限超過
                    t.Text = "[CRITICAL]" ' テキスト列に警告を表示
                    t.Flag1 = True        ' フラグ1をONにして視覚化
                    riskCount = riskCount + 1
                    reportMsg = reportMsg & "× 期限超過: " & t.Name & " (終了予定: " & t.Finish & ")" & vbCrLf
                    
                ElseIf t.Finish + warningDays >= t.Deadline Then
                    ' 【注意】期限接近
                    t.Text = "[WARNING]"
                    t.Flag2 = True        ' フラグ2をONにして視覚化
                    riskCount = riskCount + 1
                    reportMsg = reportMsg & "△ 期限接近: " & t.Name & " (終了予定: " & t.Finish & ")" & vbCrLf
                End If
                
            End If
        End If
    Next t

    ' --- 結果の出力 ---
    If riskCount > 0 Then
        MsgBox reportMsg, vbExclamation, "リスク検知完了"
    Else
        MsgBox "現在、期限に関するリスクは見つかりませんでした。", vbInformation, "チェック完了"
    End If

End Sub

コードの深掘り解説(エンジニアの視点)

# ① `If Not t Is Nothing Then` の重要性

Projectのタスクリストには、ユーザーが入力した行だけでなく、空の行も含まれています。空の行に対して `.Name` や `.Finish` を参照しようとすると、「実行時エラー 91: オブジェクト変数または With ブロック変数が設定されていません」が発生します。これを防ぐのが、この一行です。プロのコードには、必ず「ガード句(例外処理)」が必要です。

# ② `pjDateNotSet` という定数

「期限が入っていないこと」を判定する際、`t.Deadline = “”` と書きたくなりますが、日付型オブジェクトに対して文字列比較を行うのはスマートではありません。Microsoftが定義している `pjDateNotSet` を使うことで、型安全で正確な判定が可能になります。

# ③ `Flag1`, `Flag2` による視覚化

Projectには「フラグ」というBoolean型(True/False)の列が用意されています。これを利用して、リスクのあるタスクにチェックを入れることで、ガントチャート上で一目でリスク箇所を特定できるようになります。

4. 陥りやすいエラーと回避策

開発を進める中で、以下のポイントに注意してください。

  • 日付の計算精度:

Projectの内部では時間は「シリアル値」で管理されています。`t.Finish + warningDays` の計算は、基本的には「日」単位で行われますが、プロジェクトの「カレンダー(休日設定)」を考慮した計算が必要な場合は、`ProjectCalendar` オブジェクトを利用したより高度な計算が必要になります。まずはこのコードで基本をマスターしましょう。

  • 無限ループとパフォーマンス:

数千タスクある巨大なプロジェクトで、ループの中で複雑な処理を行うと、動作が重くなります。もしパフォーマンスが気になる場合は、`Application.ScreenUpdating = False` を冒頭に入れ、画面更新を止めるテクニックを検討してください。

5. まとめ:次なるステップへ

お疲れ様でした。これであなたは、単に「データを集めるマクロ」ではなく、「プロジェクトの健全性を監視するエンジン」の第一歩を踏み出しました。

  • 制約条件は「命令」、期限は「目標」。
  • 空行(Nothing)を恐れず、適切にハンドリングする。
  • フラグやテキスト列を使って、人間が直感的に判断できる形に変換する。

これらは、VBAに限らず、あらゆる業務システムの設計に通じる普遍的な原則です。

次は、この検知したリスクを、自動的にメールでプロジェクトマネージャーに送信する機能を実装してみるのも面白いかもしれませんね。

「コードを書く」ことは、目的ではありません。「課題を解決する仕組みを作る」こと。そのマインドセットこそが、あなたを真のエンジニアへと導きます。

一歩ずつ、一緒に進んでいきましょう。応援していますよ!

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