Project VBAを掌握せよ:ASAP制約の罠と計算エンジンを制する「静寂の最適化」術
現場で「MS Projectのスケジュールが意図せず跳ねる」という現象に遭遇したことはないだろうか?
特に、ASAP(可能な限り早く)制約を多用する大規模プロジェクトにおいて、VBAでタスク開始日を制御しようとすると、計算エンジンが暴走し、依存関係の連鎖でスケジュールが崩壊するのは「VBAあるある」の典型だ。
今日は、MS Projectの計算エンジンという「目に見えない怪物」を飼い慣らし、堅牢なスケジュール自動化ツールを構築するための極限の知見を授ける。
—
1. なぜASAP制約は「地雷」と化すのか
MS Projectの計算エンジンは、タスクのプロパティを書き換えるたびに「再計算(Recalculation)」を実行する。
あなたがVBAで `Task.Start = Date` を書き込んだ瞬間、Projectのエンジンは「この変更が先行・後続タスクにどう影響するか?」を即座に計算し、制約条件(ASAP等)に従って開始日を強制的に上書きし直そうとする。
もし複数のタスクに対してループで一括更新を行えば、そのたびにエンジンがフル稼働し、計算のオーバーヘッドで処理が劇的に遅延するだけでなく、制約条件の競合が発生して意図しない日付に跳ね上がるのだ。
2. 禁忌:計算エンジンの「放置プレイ」
多くの初学者は、以下のやり方でツールを組む。
‘ 【悪い例】計算エンジンがタスクごとに暴走する
For Each t In ActiveProject.Tasks
t.Start = NewDate ‘ ここで毎回再計算が走る
t.ConstraintType = pjASAP ‘ ここでも再計算が走る
Next t
これは、巨大なスプレッドシートを数式計算モードのままセル単位で書き換えるようなものだ。非効率極まりない。
3. 計算エンジンを掌握する「静寂の最適化」戦略
解決策はシンプルだ。「計算エンジンを一時停止し、一括処理し、最後に整合性を取る」。
MS Projectには `Application.Calculation` という強力な武器がある。これを利用し、トランザクションの概念を導入するのだ。
プロダクション環境に耐えうる実装コード
以下のコードは、計算エンジンを一時停止(Manual)し、安全にASAP制約を適用する、保守性の高いテンプレートだ。
Public Sub OptimizeTaskScheduling()
Dim proj As Project
Dim tsk As Task
Dim oldCalcMode As Long
Set proj = ActiveProject
‘ 1. 計算エンジンを一時停止(静寂の確保)
oldCalcMode = proj.Calculation
proj.Calculation = pjManual
On Error GoTo ErrorHandler
‘ 2. 一括適用プロセス
For Each tsk In proj.Tasks
If Not tsk Is Nothing Then
‘ 完了済みタスクを除外するなどのバリデーションを入れるのがプロの作法
If Not tsk.Summary Then
‘ 制約をASAPに設定しつつ、開始日を強制固定する
‘ ※注意: ConstraintTypeを先に設定するのがコツ
tsk.ConstraintType = pjASAP
tsk.Start = GetTargetDate(tsk) ‘ 別途計算ロジック
End If
End If
Next tsk
‘ 3. 計算エンジンを再開(一括で整合性をとる)
proj.Calculation = oldCalcMode
proj.CalculateAll
MsgBox “スケジュール更新完了”, vbInformation
Exit Sub
ErrorHandler:
‘ 異常終了時も必ず計算モードを元に戻すこと
proj.Calculation = oldCalcMode
MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub
4. 堅牢な設計のための3つの鉄則
① 制約条件の「順序」がすべてを決める
`Start` を書き込む前に `ConstraintType` を設定せよ。先に日付を書き込むと、Projectのエンジンが「制約違反」と判定し、自動的に日付を修正してしまうリスクがある。
② データベース/外部ファイル連携の注意
CSVやExcelから日付を読み込む際、`Date` 型のキャストミスは致命的だ。特にProjectの内部日付はミリ秒単位の倍精度浮動小数点数であることを忘れてはならない。必ず `CDate()` で厳密に型変換し、空セル(Null)のハンドリングを徹底すること。
③ 「計算エンジン」の再開タイミング
`proj.CalculateAll` は最後の最後、全データのセットが終わった後に一度だけ叩く。これをループ内で実行するのは重罪である。
—
結びに:エンジニアとしての矜持
MS ProjectのVBAは、単なる「自動化スクリプト」ではない。プロジェクトという複雑系を制御するための「司令塔」だ。
計算エンジンという怪物を力でねじ伏せるのではなく、「一時停止」という沈黙の時を与え、一気に論理を構築する。 このアーキテクトとしての視点を持つだけで、あなたの作るツールは、現場を混乱させるバグメーカーから、チームを救う武器へと進化する。
次回の開発でこの手法を適用したとき、処理速度の違いに驚くだろう。それが「極限の知見」を手にした者の証だ。健闘を祈る。
