伝説のアーキテクトが説く:Project VBAにおける「リソース過負荷」の自動解消アルゴリズム
多くのVBAエンジニアは、Project VBAを操作する際、UI上の操作をマクロ記録するレベルで止まっている。しかし、リソースマネジメントという「生存競争の激しい領域」では、そんな甘い実装は即座にメモリリークやパフォーマンス低下、果てはプロジェクトスケジュールの崩壊を招く。
今回は、`Resource.WorkContour`と`Assignment.Work`を支配し、過負荷を検知して自動でタスクを再割り当てする「リソース最適化エンジン」の設計思想と実装を授ける。
—
1. なぜ「単純なループ」で再割り当てしてはいけないのか
プロジェクト管理におけるリソース平準化は、単なる条件分岐の積み重ねではない。最も陥りやすい罠は、「計算量(O(n^2)以上)の増大」だ。
- WorkContourの罠: プロジェクト上のリソース配分は、日付ごとの`TimephasedData`として保持されている。これを逐一ループで回して合計値を算出するのは、数千行のプロジェクトでは自殺行為だ。
- 整合性の崩壊: `Assignment.Work`を書き換える際は、関連する`Task.Start`や`Task.Finish`との整合性を保たなければならない。これを無視すると、Project側で「依存関係の循環エラー」が発生し、計算が停止する。
堅牢な設計のためには、「計算用のメモリ内マップ(辞書オブジェクト)」を作成し、最小限の書き込み操作で一括更新するアーキテクチャが不可欠である。
—
2. リソース最適化エンジンの設計方針
1. スナップショットの作成: 現在の割り当て状況を`Scripting.Dictionary`にキャッシュする。
2. 過負荷判定: 閾値(例: 100%)を超えたリソースIDを特定。
3. 空きリソースの探索: スキルセットと稼働率が低いリソースを優先的に選定。
4. トランザクション管理: 変更を適用する前に、必ず`CalculationMode`を一時停止する。
—
3. 実践:プロダクションコード
以下のコードは、過負荷リソースを特定し、空きがあるリソースへ割り当てを移動させるコアロジックだ。
Option Explicit
‘ 伝説のアーキテクトによるリソース平準化エンジン
Public Sub AutoReallocateResources()
Dim proj As Project
Dim res As Resource
Dim asn As Assignment
Dim targetRes As Resource
Dim threshold As Double: threshold = 480 ‘ 1日8時間=480分を閾値とする
Set proj = ActiveProject
‘ パフォーマンスの最適化:計算モードを停止
Application.Calculation = pjManual
On Error GoTo Cleanup
‘ 全リソースの負荷状況を解析(擬似的な負荷マップ作成)
For Each res In proj.Resources
If IsOverloaded(res, threshold) Then
‘ 過負荷リソースのタスクを特定
For Each asn In res.Assignments
‘ 代替リソース候補を探索(ここではシンプルに別リソースへ振る)
Set targetRes = FindAvailableResource(asn.Task, res)
If Not targetRes Is Nothing Then
‘ 割り当て変更
asn.ResourceID = targetRes.ID
Debug.Print “タスク [” & asn.Task.Name & “] を ” & res.Name & ” から ” & targetRes.Name & ” へ移動”
End If
Next asn
End If
Next res
Cleanup:
‘ 最後に計算を再開し、整合性を強制同期
Application.Calculation = pjAutomatic
If Err.Number <> 0 Then MsgBox “エラー発生: ” & Err.Description
End Sub
‘ 負荷判定ロジック
Private Function IsOverloaded(r As Resource, limit As Double) As Boolean
‘ TimephasedDataを使用して特定日の工数を確認する手法が最も正確
‘ ここでは簡略化のためAssignmentの合計稼働率で判定
If r.Work > (limit 5) Then ‘ 週間の総負荷で判定
IsOverloaded = True
End If
End Function
‘ 最適リソース選定ロジック
Private Function FindAvailableResource(t As Task, currentRes As Resource) As Resource
Dim r As Resource
For Each r In ActiveProject.Resources
‘ 稼働率が低く、かつ現在のリソースとは別人を返す
If r.ID <> currentRes.ID And r.Work < 400 Then
Set FindAvailableResource = r
Exit Function
End If
Next r
End Function
---
4. 運用上の極意:バグを出さないための注意点
- CalculationModeの制御: 上記コードで最も重要なのは `Application.Calculation = pjManual` だ。これを行わないと、1つの割り当てを変更するたびにProject全体が再計算を行い、数万行のプロジェクトでは数十分かかることになる。
- データベース連携: もしこのデータを外部SQL ServerやExcelへエクスポートするなら、Projectの`Guid`をキーにすること。名前で管理するのは、リソース名が重複した瞬間にシステムが破綻する「アマチュアの設計」だ。
- Undo(元に戻す)の制約: VBAによる変更は、一度実行するとUndoが効かない場合が多い。必ずバックアップをとった環境で実行し、変更ログをテキストファイルに書き出す仕組みを併用せよ。
最後に
リソース最適化は、単なる作業の割り振りではない。プロジェクトの血流を整える外科手術だ。このコードをベースに、各組織のスキルセット管理(Resource.Notesやカスタムフィールド)を組み込めば、君だけの強力な自動化エンジンが完成するはずだ。
技術は、常に「最悪の事態」を想定した者が制する。健闘を祈る。
