プロジェクトを殺す「リソースの飽和」を、VBAで論理的に制御する
プロジェクトマネジメントにおいて、最も愚かな行為は「リソースの限界を無視してスケジュールを引くこと」だ。MS Projectの自動スケジューリングは便利だが、複雑な依存関係やカスタム優先度が絡むと、しばしば意図せぬ「無理な後ろ倒し」を誘発する。
今日は、Project VBAを使い倒し、リソースのオーバーアロケーション(過負荷)をプログラムで強制的に解消する「優先度制御スケジューラ」の設計思想を伝授する。
—
1. なぜ「標準機能」だけでは限界があるのか
MS Projectの標準「平準化(Leveling)」機能は、あくまでアルゴリズムに依存するブラックボックスだ。現場で求められるのは、「ビジネス上の重要度(優先度)」に基づいた、人間が納得できる順序立てである。
我々エンジニアがやるべきは、「負荷集中ポイントの特定 → 優先度による並び替え → 依存関係を維持したままのシフト」というロジックを、VBAで確実に実装することだ。
2. 堅牢な設計のための3つの鉄則
1. 計算の冪等性(べきとうせい)を保つ: 何度実行しても同じ結果になるようにすること。タスクの開始日を直接いじるのではなく、必ず `Task.ConstraintDate` や `Task.Start` を「一度クリアしてから再設定する」という手順を踏む。
2. 遅延の伝播を考慮する: 優先度の低いタスクを後ろにずらすと、後続タスク(Successor)にも遅延が連鎖する。これを無視するとスケジュールが崩壊する。`Task.Link` を辿る再帰処理を恐れてはならない。
3. カスタムフィールドの活用: 優先度は `Number1` 等のカスタムフィールドに持たせ、プログラムが参照する「絶対基準」とする。
—
3. 実装:優先度ベースの自動ソート・シミュレーター
以下は、選択したリソースのオーバーアロケーションを検出し、優先度順に並び替えて日付を調整するプロトタイプだ。
Option Explicit
‘ プロジェクト内の全リソース負荷を解消するためのメインルーチン
Public Sub OptimizeResourceLoad()
Dim tsk As Task
Dim res As Resource
Dim tskCol As Collection
‘ 1. 対象リソースの過負荷タスクを抽出
‘ 実際の実務では特定の期間やリソースIDでフィルタリングすること
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
If tsk.Overallocated Then
‘ Number1フィールドを優先度(1が高優先)として定義
Debug.Print “Overallocated Task: ” & tsk.Name & ” Priority: ” & tsk.Number1
End If
End If
Next tsk
‘ 2. 優先度順にソート(簡易的なバブルソート例)
‘ 本番環境では、コレクションをクイックソートするアルゴリズムを推奨
Call SortTasksByPriority
‘ 3. 後ろ倒しの実行(ロジックの核)
Call ShiftTasksBasedOnPriority
End Sub
Private Sub ShiftTasksBasedOnPriority()
Dim tsk As Task
Dim nextStart As Date
‘ プロジェクトの基準日から開始日を再計算していく
nextStart = ActiveProject.ProjectStart
‘ 優先度の高い順に並んだタスクを順次配置
‘ ここでは単純化のため、開始日を強制的にセットするが
‘ 実際は依存関係(Predecessors)を考慮し、前タスク終了後を指定する
For Each tsk In GetSortedTaskList()
If tsk.Start < nextStart Then
tsk.Start = nextStart
End If
' タスクの期間分だけnextStartを更新
nextStart = tsk.Finish
Next tsk
MsgBox "リソースの平準化が完了しました。", vbInformation
End Sub
---
4. 運用上の注意点と「罠」
- カレンダー設定を無視するな: `tsk.Start = nextStart` と書くと、土日や祝日を無視してタスクが割り当てられる可能性がある。必ず `Application.DateAdd` メソッドを使い、プロジェクトカレンダーの稼働日を考慮すること。
- Undo(元に戻す)の罠: VBAで大量のタスクを操作すると、標準のUndoスタックが溢れる。大規模プロジェクトで実行する場合は、必ず実行前に `FileSave` するか、バックアッププロジェクトを生成するルーチンを組み込むこと。
- パフォーマンス: `ActiveProject.Tasks` を直接ループさせるのは極めて低速だ。必要なタスクだけをフィルタリングした `SelectTaskField` 等を駆使し、オブジェクトの参照回数を最小限に絞るのが、熟練者のコードである。
最後に:自動化は「責任」である
ツールでスケジュールを書き換えるということは、そのプロジェクトの「意思決定」をコードが代行するということだ。
優先度をどう定義するか、どのタスクを「捨てる(遅延させる)」かという判断は、エンジニアではなくPMとの協議が必要だ。ツールはあくまでその判断を「実行可能にするための演算機」であるべきだ。
このコードを叩き台に、君のプロジェクトの仕様に合わせて磨き上げてほしい。それが、世界最高峰の自動化エンジニアへの第一歩だ。
