スケジュールの「鎖」を解き放て:Project VBAで制約条件を制御し、真の最短工期を導き出す極意
こんにちは。現場の最前線で複雑なプロジェクトの自動化を設計している、あなたの先輩エンジニアです。
「マクロの記録」を使って、なんとか作業を自動化できた。そんな喜びを感じている方も多いでしょう。でも、もしあなたが「プロジェクトの遅延を防ぎたい」「もっと効率的なスケジュールを提案したい」と願うなら、次に乗り越えるべき壁があります。
それは、「人間が手入力した制約条件(Constraints)が、スケジュールの計算エンジンを邪魔している」という問題です。
今日は、一歩上のエンジニアへとステップアップするために、Project VBAの核心部である「制約条件の制御」と、それを利用した「スケジュール最適化アルゴリズム」の考え方を伝授します。ここをクリアすれば、あなたの作るツールは「ただの自動化」から「意思決定を支援するシステム」へと進化しますよ。
1. なぜスケジュールは「動かない」のか?
Microsoft Projectの凄さは、タスク間の依存関係(先行・後続)に基づいて、計算エンジンが自動的に日付を割り当てる点にあります。
しかし、現場ではよくこんなことが起こります。
- 「この作業は、絶対に〇月〇日に始めなければならない」
- 「このタスクは、遅くともこの日には終わらせておきたい」
これらを管理するために、ユーザーはタスクに「制約条件(Constraint)」を設定します。例えば「開始指定(Must Start On)」などです。
ここが落とし穴!
制約条件は、計算エンジンに対する「命令(強制力)」です。
依存関係がどれほど完璧でも、強力な制約条件(鎖)が一つあるだけで、プロジェクト全体のスケジュールは、その「鎖」に引きずられて不自然に伸びてしまいます。
プロフェッショナルなエンジニアは、こう考えます。
「今見えている終了日は、本当の最短終了日か? それとも、誰かが設定した制約条件に縛られた『偽の姿』なのか?」
2. 制約条件の種類を理解する(プロへの第一歩)
VBAを操る前に、まずはProjectが持っている「鎖」の種類を知っておきましょう。`Task.ConstraintType` プロパティで取得できます。
| 定数名 | 意味 | エンジンへの影響 |
|---|---|---|
| `pjTaskConstraintNone` | 制約なし (ASAP/ALAP) | 理想的な状態。 依存関係に従って自由に動く。 |
| `pjTaskConstraintStartNoEarlierThan` | 開始前指定 | 「これより前には始められない」という緩い制約。 |
| `pjTaskConstraintMustStartOn` | 開始指定 | 強力な制約。 指定日以外には絶対に動かない。 |
| `pjTaskConstraintStartNoLaterThan` | 開始後指定 | 「これより遅れてはならない」という制約。 |
「マクロの記録」では、単に日付を書き換えるだけのコードになりがちです。しかし、本物のエンジニアは、この `ConstraintType` 自体を操作します。
3. 最適化アルゴリズムの実装:制約の「一時解放」
では、いよいよ本題です。
「現在の制約条件をバックアップし、一度すべてを『制約なし(ASAP)』に解放して最短期間を算出し、その後、元の状態に戻す」という、プロ仕様の最適化ロジックを実装してみましょう。
実装のイメージ図
1. 【調査】 すべてのタスクをスキャンし、制約があるタスクを特定する。
2. 【保存】 制約の種類と日付をメモリ(Collection)に退避させる。
3. 【解放】 制約を `pjTaskConstraintNone` に書き換え、再計算を実行。
4. 【算出】 解放された状態での「プロジェクト終了日」を記録。
5. 【復元】 保存しておいたデータを使って、元の制約を正確に再設定する。
実践的なVBAコード
Option Explicit
' 制約情報を保持するためのカスタム型
Private Type ConstraintInfo
TaskID As Long
CType As PjConstraintType
CDate As Date
End Type
Sub OptimizeScheduleByReleasingConstraints()
Dim t As Task
Dim originalConstraints As New Collection
Dim info As ConstraintInfo
Dim theoreticalEnd As Date
Dim currentEnd As Date
' 現在のプロジェクト終了日を記録
currentEnd = ActiveProject.ProjectFinish
On Error GoTo ErrorHandler
' --- STEP 1 & 2: 制約の特定とバックアップ ---
For Each t In ActiveProject.Tasks
' 空のタスク(削除済みなど)はスキップ
If Not t Is Nothing Then
' 制約が「なし(None)」以外の場合、バックアップ対象とする
If t.ConstraintType <> pjTaskConstraintNone Then
info.TaskID = t.ID
info.CType = t.ConstraintType
info.CDate = t.ConstraintDate
' Collectionに構造体を格納(IndexをTaskIDにすると復元が楽)
originalConstraints.Add info, CStr(t.ID)
' --- STEP 3: 制約の解放 ---
' 制約を「なし」に変更することで、計算エンジンを自由にさせる
t.ConstraintType = pjTaskConstraintNone
End If
End If
Next t
' --- STEP 4: 再計算と最短終了日の算出 ---
' 全ての制約を解いた状態で、プロジェクト全体を再計算
ActiveProject.Calculate
theoreticalEnd = ActiveProject.ProjectFinish
' 結果の表示
MsgBox "【最適化シミュレーション完了】" & vbCrLf & _
"現在の終了日: " & currentEnd & vbCrLf & _
"理論上の最短終了日: " & theoreticalEnd & vbCrLf & vbCrLf & _
"差分: " & DateDiff("d", theoreticalEnd, currentEnd) & " 日", vbInformation, "分析結果"
' --- STEP 5: 制約の復元 ---
' ユーザーが元のスケジュールに戻れるよう、保存した情報を書き戻す
Dim item As Variant
For Each item In originalConstraints
Set t = ActiveProject.Tasks(CStr(item.TaskID))
t.ConstraintType = item.CType
t.ConstraintDate = item.CDate
Next item
' 最終的な再計算
ActiveProject.Calculate
MsgBox "元の制約条件を復元しました。", vbOKOnly, "完了"
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
' エラー時も可能な限り復元を試みる(実務ではここが重要!)
Resume Next
End Sub
4. プロが教える、陥りやすいエラーと回避策
このコードを動かす際、あるいは自分で改良する際に、以下の3点に注意してください。これを知っているだけで、デバッグの時間が劇的に減ります。
① 「空のタスク」の罠
`For Each t In ActiveProject.Tasks` でループを回すと、ユーザーが削除したタスク(メモリ上には残っている)に当たることがあります。必ず `If Not t Is Nothing Then` で存在チェックをしてください。これを忘れると `Object Required` エラーで止まります。
② `ConstraintDate` の扱い
制約の種類(`ConstraintType`)だけを変えても、日付(`ConstraintDate`)が残っていると、計算エンジンが混乱することがあります。必ず「タイプ」と「日付」をセットで操作する癖をつけましょう。
③ 処理の重み(パフォーマンス)
タスクが数千件ある巨大なプロジェクトで、ループの中で毎回 `ActiveProject.Calculate` を呼び出すと、Excelがフリーズしたようになります。
「計算は、全ての制約を解放し終えた後に、たった一度だけ行う」。これが、高速なツールを作る鉄則です。
最後に:エンジニアとしての視点
今回紹介した手法は、単に「日付を動かす」ためのものではありません。
「人間が設定した制約(意図的な制限)」と「プロジェクトの物理的な限界(計算エンジンによる理論値)」を切り分けて考えるための、分析的なアプローチです。
このロジックを応用すれば、「どのタスクの制約を解除すれば、プロジェクト全体が最短になるか?」という、より高度なボトルネック分析ツールを作ることも可能です。
一歩ずつ、コードの裏側にある「ロジック」を理解していけば、必ずProject VBAを自由自在に操れるようになります。応援していますよ。頑張りましょう!
