「期限」と「計算」の乖離を見抜く。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)」の間に生じる摩擦を、プログラムによって可視化する技術です。
自動化の真価は、人間が「気づかなければならないこと」を、プログラムが「気づかせてくれること」にあります。
このコードをベースに、例えば「遅延しているタスクをメールでプロジェクトマネージャーに飛ばす」といった拡張も可能です。一歩ずつ、コードに魂を込めていってください。
応援していますよ。次はもっと複雑な、リソース平準化の自動制御に挑戦してみましょう。
