【テクニカル・上級編】実務中級:リソース平準化と制約条件の競合をVBAで解決する優先順位調整 – Project VBA解析バイブル

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

制約とリソースの戦場を支配する:MS Project スケジュール計算エンジンの極限制御

大規模プロジェクトの管理において、MS Projectの「リソース平準化(Resource Leveling)」は、諸刃の剣である。

リソースの過不足を解消しようとエンジンを回した瞬間、緻密に組まれた「制約条件(Constraints)」が悲鳴を上げ、スケジュールは予測不能な形で押し出される。現場のPM(プロジェクトマネージャー)は、制約を優先してリソースの衝突を無視するか、リソースを優先してマイルストーンを破壊するかという、不毛な二択を迫られることになる。

シニアエンジニア、あるいは社内システムを設計するアーキテクトにとって、この問題は「設定の不備」ではなく、「計算エンジンの制御ロジックの欠如」として捉えるべきだ。

本稿では、VBAを用いて「制約条件」と「リソース平準化」の競合を論理的に解体し、ビジネスルールに基づいた自動修正を行う、極めて堅牢な制御アーキテクチャについて解説する。

1. 根本的な問題:計算エンジンの決定論的挙動の欠如

MS Projectの計算エンジンは、タスクの制約条件(Must Start On, As Soon As Possible等)と、リソースの利用可能性を同時に解こうとする。しかし、これらが衝突した際、エンジンの挙動は「制約の硬さ」に依存する。

  • Hard Constraint (pjTaskMustStartOn等): エンジンはこの制約を絶対とし、リソースが不足していてもタスクを動かさない。結果、リソースの重複(Over-allocation)が残る。
  • Soft Constraint (pjTaskAsSoonAsPossible等): エンジンはリソース平準化の要請に従い、制約を無視してタスクをスライドさせる。

実務における真の課題は、「どの制約を『硬い』ものとし、どの制約を『柔らかい』ものとして再定義するか」という意思決定の自動化にある。これを手動で行うのは、数千タスク規模のプロジェクトでは不可能だ。

2. アーキテクチャ設計:競合解消のアルゴリズム

我々が構築すべきは、単なるループ処理ではない。以下のフェーズを持つ、決定論的な制御プロセスである。

1. スキャンフェーズ: リソース過不足(Over-allocation)が発生しているタスクを特定する。
2. 衝突検知フェーズ: 特定されたタスクが、どの種類の制約(ConstraintType)によってスケジュールがロックされているかを判定する。
3. 意思決定フェーズ: ビジネスロジック(例:重要度、コスト、クリティカルパスの有無)に基づき、「制約の緩和」か「リソースの追加」かを決定する。
4. 実行フェーズ: 制約のタイプを書き換え、計算エンジンを再トリガーする。

3. 実装:極限のメモリ管理とパフォーマンス最適化

大規模なプロジェクトファイル(数千〜数万タスク)を扱う際、VBAエンジニアが陥る最大の罠は、COMオブジェクトのライフサイクル管理の失敗によるメモリリークと、再計算のオーバーヘッドである。

以下のコードは、単なる「動くコード」ではない。メモリ消費を最小限に抑え、大規模環境での実行を想定したプロフェッショナル仕様のフレームワークである。

Option Explicit

' Windows API: プロセスの応答性を維持するためのスリープ(必要に応じて)
' 大規模処理中にUIがフリーズするのを防ぎ、システム的なデッドロックを回避する

If VBA7 Then

Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)

Else

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

End If

' 定数定義: MS Projectの内部定数(参照設定がない環境への配慮) Private Const pjTaskMustStartOn As Long = 3 Private Const pjTaskAsSoonAsPossible As Long = 0 Private Const pjTaskStartNoFinish As Long = 4 ''' <summary> ''' リソース平準化と制約条件の競合を解決するメインエンジン ''' </summary> Public Sub ResolveConstraintResourceConflict() Dim app As MSProject.Application Set app = MSProject fact.Application Dim t As MSProject.Task Dim conflictCount As Long Dim startTime As Double On Error GoTo ErrorHandler ' パフォーマンス最適化: 計算モードをマニュアルにし、画面更新を停止 app.Calculation = pjManual app.ScreenUpdating = False startTime = Timer conflictCount = 0 ' 1. スキャンフェーズ: 全タスクを走査 ' Note: Tasksコレクションの直接ループは、大規模プロジェクトではメモリ負荷が高い。 ' 必要に応じて、特定のフィルタリングされたViewからアクセスすることを検討せよ。 For Each t In app.ActiveProject.Tasks If Not t Is Nothing Then ' リソースの過不足が発生しているかチェック If t.ResourceOverallocated Then ' 2. 衝突検知フェーズ ' 制約条件が "Must Start On" 等の「硬い制約」であるかを確認 If t.ConstraintType = pjTaskMustStartOn Or t.ConstraintType = pjTaskMustFinishOn Then ' 3. 意思決定フェーズ (ここがビジネスロジックの中核) ' 例: タスクの優先度(Priority)が低い場合は、制約を緩和(Soft)する If t.Priority < 500 Then ' 500はMS Projectの標準的な閾値 ' 4. 実行フェーズ: 制約の書き換え ' 制約を ASAP (As Soon As Possible) に変更することで、 ' 次回の平準化実行時にエンジンがタスクを動かせるようにする。 t.ConstraintType = pjTaskAsSoonAsPossible conflictCount = conflictCount + 1 ' メモリ負荷軽減のため、適宜システムに制御を戻す(極めて大規模な場合) If conflictCount Mod 100 = 0 Then DoEvents End If End If End If End If Next t ' 最終的な計算の再実行 app.Calculate ' 状態の復元 app.Calculation = pjAutomatic app.ScreenUpdating = True MsgBox "処理完了: " & conflictCount & " 件の制約を緩和しました。" & vbCrLf & _ "実行時間: " & Format(Timer - startTime, "0.00") & " 秒", vbInformation Exit Sub ErrorHandler: ' エラーハンドリング: オブジェクトの解放を確実に行う app.Calculation = pjAutomatic app.ScreenUpdating = True MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical ' メモリ解放の儀式 Set t = Nothing Set app = Nothing End Sub

4. アーキテクトの視点:レガシー環境とシステム間連携

このソリューションを実務に投入する際、以下の3点に留意せよ。

オブジェクトの明示的解放

VBAにおける `Set t = Nothing` は、単なる作法ではない。MS Projectのような巨大なCOMサーバーを操作する場合、参照カウントが適切に減少しなければ、Excelや他の連携アプリケーションとの間で、プロセスがゾンビ化(メモリ上に残り続ける現象)を引き起こす。特に、ループ内でオブジェクトを生成・破棄する場合は、ライフサイクルを厳格に管理せよ。

決定論的なデバッグ

「なぜこのタスクが動かなかったのか?」という問いに対し、「エンジンの仕様です」という回答はエンジニアとして失格だ。制約条件の変更履歴を、カスタムプロパティ(`t.SetCustomField`)にログとして残す仕組みを組み込め。これにより、後からの監査(Audit)が可能になる。

システム間連携への拡張

このロジックは、MS Project単体で完結させるべきではない。理想的なアーキテクチャでは、リソースのマスターデータはERP(SAP等)にあり、制約の優先順位ルールは外部の意思決定エンジン(Python/C#等)からAPI経由で注入されるべきだ。VBAは、その「実行部隊(Execution Layer)」として、COMインターフェースを介して指示を具現化する役割に徹する。

結論

リソース平準化と制約条件の競合は、プロジェクト管理における「エントロピーの増大」そのものである。これをVBAで制御するということは、単にコードを書くことではなく、プロジェクトの論理構造をコードによって再定義することを意味する。

エンジニアが目指すべきは、ツールを使う者ではなく、計算エンジンの挙動を完全に支配する者である。

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