Project VBAの深淵:Assignment.Delayを制御し、リソース競合を物理的限界まで排除する
MS ProjectのVBAを扱う際、多くの開発者は`Task`の開始日や終了日を操作することに終始する。だが、真のシニアエンジニアは知っている。プロジェクトの成否は「リソースがいつ動き出し、どれほどの負荷を背負うか」という、Assignment(割り当て)の精緻な制御に集約されることを。
今日は、標準的なスケジューリングエンジンが見逃す「リソース競合」を、`Assignment.Delay`をハックして解決するアーキテクチャについて語ろう。
—
1. なぜ「Assignment.Delay」なのか
MS Projectの標準機能では、リソースの競合が発生した際、タスクそのものを後ろ倒しにするのが一般的だ。しかし、これではクリティカルパスが不必要に伸びる。
我々が求めるのは、「タスクの開始日は維持しつつ、特定リソースの参画のみを遅らせる」という柔軟性だ。`Assignment.Delay`を操作することで、リソースの稼働開始をオフセットさせ、オーバーアロケーション(過負荷)を局所的に解消する。これは、大規模プロジェクトにおける稼働率調整の最終兵器である。
—
2. 実装の指針:メモリ管理と安全な操作
VBAは、MS ProjectのCOMオブジェクトモデル上で動作する。`Application.ActiveProject.Assignments`へのアクセスは、頻度が高まればメモリリークやオートメーションエラーを誘発する温床となる。
以下の点に注意せよ。
- オブジェクトの明示的解放: `Set obj = Nothing`を徹底し、参照カウンタを操作する。
- 再計算の抑制: `Application.Calculation = pjManual` を一時的に設定し、ループ毎の再計算によるパフォーマンス低下を防ぐ。
- エラーハンドリング: `On Error Resume Next` での逃げは厳禁。各Assignmentの有効性を `Is Nothing` で厳密に検証する。
—
3. 実践コード:リソース割り当て遅延制御エンジン
このコードは、指定したタスクに含まれるリソースに対し、負荷分散のために個別の遅延を適用するプロトタイプだ。
‘ @description リソース割り当ての遅延を制御し、競合を回避する
‘ @param taskID ターゲットタスクのID
‘ @param resName 調整対象のリソース名
‘ @param delayDays 遅延させる日数
Public Sub OptimizeAssignmentDelay(ByVal taskID As Long, ByVal resName As String, ByVal delayDays As Long)
Dim proj As Project
Dim tsk As Task
Dim assn As Assignment
Set proj = ActiveProject
Set tsk = proj.Tasks(taskID)
‘ パフォーマンス向上のため再計算を停止
Application.Calculation = pjManual
On Error GoTo Cleanup
‘ 指定タスク内の割り当てを走査
For Each assn In tsk.Assignments
If assn.ResourceName = resName Then
‘ Assignment.Delayは「分」単位での指定が基本
‘ 1日 = 480分(標準カレンダー設定に依存)
assn.Delay = delayDays 480
Debug.Print “Applied delay to ” & resName & “: ” & delayDays & ” days.”
End If
Next assn
Cleanup:
‘ オブジェクトの明示的解放
Set assn = Nothing
Set tsk = Nothing
Set proj = Nothing
‘ 再計算を再開
Application.Calculation = pjAutomatic
If Err.Number <> 0 Then
MsgBox “Error: ” & Err.Description, vbCritical
End If
End Sub
—
4. 極限の知見:システム間連携とWindows APIの活用
さらに踏み込むなら、プロジェクトの外部にある「リソース稼働実績DB」や「勤怠システム」と同期させることが不可欠だ。
もしVBA単体で限界を感じるなら、`kernel32.dll`を用いて高精度タイマーを取得し、処理のボトルネックを特定するか、あるいはVB.NETでCOMアドインを構築して、メモリ空間を分離すべきだ。特に大規模ファイル(数千タスク超)を扱う場合、VBAのガベージコレクションは頼りにならない。
アーキテクトからの忠告
1. カレンダーの影響を考慮せよ: `Assignment.Delay`はベースカレンダーの稼働日に依存する。単なる数値計算ではなく、`Project.Calendar`オブジェクトを精査し、非稼働日をスキップする計算ロジックを組み込むこと。
2. Undoスタックの肥大化に注意: 多数のAssignmentをループで書き換えると、Undoバッファが圧迫され、Project自体がクラッシュする。バッチ処理の合間に `DoEvents` を挟むか、あるいはトランザクション処理の単位を細かく分割せよ。
—
結びに代えて
MS ProjectのVBAは、単なるマクロの集合体ではない。それは、プロジェクトという「生きた有機体」の血流を調整する外科手術のようなものだ。
リソースの遅延を自在に操れるようになった時、君たちはプロジェクトマネージャーから頼まれる「調整」という名の魔法から解放され、真に制御可能なシステムアーキテクトへと進化するだろう。
コードを書け。ただし、その背後にあるメモリとオブジェクトの鼓動を感じながら。
