こんにちは!プロジェクト管理の現場で、日々スケジュール調整に頭を悩ませていませんか?
「定例会議だから毎週月曜に固定したい」「この先行研究タスクは、納期ギリギリまで後ろ倒し(ALAP)にしたい」「でも、何百件もあるタスクを一つずつ手動で制約条件に変更していくなんて……やってられない!」
そんなマクロの記録から一歩抜け出したいあなたへ。今回は、Project VBAの心臓部である「スケジュール計算エンジンの制御」、そして「制約条件のテンプレート化」をテーマに、ルールベースで自動的に適切な制約を適用するスマートな自動化エンジンの作り方を解説します。
ここをクリアすれば、Project VBAの基本と、オブジェクトのライフサイクルを操る感覚がグッと身につきますよ。さあ、一緒にプロの扉を開きましょう!
—
1. なぜ「制約条件のテンプレート化」が必要なのか?
MS Projectのスケジュールエンジンは非常に優秀です。何も指定しないと、基本的には「できる限り早く(ASAP)」タスクをスケジュールしようとします。
しかし、実際のプロジェクトでは様々な「大人の事情(制約)」が入ってきます。
- 「できる限り遅く(ALAP)」:リソースの負荷分散やコスト発生を限界まで遅らせたいタスク。
- 「指定日以降に開始(SNET)」:資材の納品日が決まっているタスク。
- 「指定日完了(FNET)」:マイルストーンや絶対に落とせないリリース日。
これらを人間が手作業でポチポチ設定していると、ヒューマンエラーの温床になります。だからこそ、「タスクの名前やカスタムフィールドの条件を見て、VBAが瞬時に最適な制約を自動適用する仕組み(テンプレート化)」が現場を救うのです。
—
2. Project VBAの基本:制約条件を操るプロパティ
MS ProjectのVBAでは、タスク(Taskオブジェクト)の制約条件は主に以下の2つのプロパティで制御します。
1. `ConstraintType`(制約の種類)
- 定数を使って指定します(例:`pjConstraintASAP`、`pjConstraintALAP`、`pjConstraintSNET`など)。
2. `ConstraintDate`(制約の日付)
- 「〇月〇日以降」といった日付指定が必要な制約(SNETやMEOなど)の場合にセットします。ASAPやALAPの場合は不要(または無視されます)です。
⚠️ ここが現場の落とし穴!
> 初学者がやりがちなのが、「制約日付が必要なタイプなのに、`ConstraintDate`を空のままにしてエラーになる」、あるいは「不要な日付が残っていてスケジュールがバグる」というミスです。
> VBAで制約を操作するときは、「どの制約タイプには、どの日付が必要か」のルールをコード側できっちり制御してあげることが、バグを防ぐ極意です。
—
3. 実装コード:ルールベース制約適用エンジン
それでは、実際の現場でそのままコピペして使える実用的なコードをご紹介します。
このコードは、アクティブなプロジェクト内の全タスクを走査し、「タスク名」や「カスタムテキストフィールド」のキーワードを読み取って、自動的に適切な制約(ASAP, ALAP, SNETなど)を適用するエンジンです。
Sub ApplyConstraintTemplates()
Dim tsk As Task
Dim appliedCount As Long
‘ 画面描画を停止して処理速度を爆発的に上げる(お作法です!)
Application.ScreenUpdating = False
appliedCount = 0
‘ プロジェクト内のすべてのタスクをループ処理
For Each tsk In ActiveProject.Tasks
‘ 削除されたタスクやサマリータスク(プロジェクト全体の見出し)を除外
If Not tsk Is Nothing Then
If Not tsk.Summary Then
‘ ルール1: タスク名に「【ALAP】」が含まれている場合
If InStr(1, tsk.Name, “【ALAP】”, vbTextCompare) > 0 Then
tsk.ConstraintType = pjConstraintALAP
appliedCount = appliedCount + 1
‘ ルール2: タスク名に「【納品】」が含まれ、かつ制約日付が設定されている場合の例
ElseIf InStr(1, tsk.Name, “【納品】”, vbTextCompare) > 0 Then
tsk.ConstraintType = pjConstraintSNET
‘ ※ここでは例として「着手予定日(Start)」を制約日として流用
If IsDate(tsk.Start) Then
tsk.ConstraintDate = tsk.Start
End If
appliedCount = appliedCount + 1
‘ ルール3: デフォルト(何もヒットしないものはASAPでガチガチに固めない等、必要に応じて)
‘ 今回はデフォルトルールとして、特に指定がなければASAPを強制適用する例
‘ Else
‘ tsk.ConstraintType = pjConstraintASAP
End If
End If
End If
Next tsk
‘ 画面描画を復元
Application.ScreenUpdating = True
‘ 完了メッセージ
MsgBox “処理が完了しました。” & vbCrLf & _
“制約テンプレートを適用したタスク数: ” & appliedCount & “件”, _
vbInformation, “制約自動化エンジン”
End Sub
—
4. コードの深掘りポイント(エンジニアの知見)
上記のコードには、現場で生き残るためのテクニックが詰まっています。
- `Application.ScreenUpdating = False` の重要性
MS Projectは、タスクのプロパティを1つ書き換えるたびに、背後でスケジュール計算エンジン(CPM:クリティカルパス法)が走り、画面を再描画しようとします。数千件のタスクがあるプロジェクトでこれをやると、数分待ちぼうけを食らうことになります。処理の最初で画面を止め、最後に戻す。これはVBAエンジニアの鉄則です。
- サマリータスク(`tsk.Summary`)の除外
プロジェクトの親階層にあたるサマリータスクに直接制約をかけようとすると、スケジュールエンジンが混乱し、予期せぬエラーや日付のズレを引き起こします。「葉(リーフ)にあたる末端のタスクのみにルールを適用する」というガード条件は必ず入れましょう。
—
5. まとめ:ここをクリアすれば、Project VBAはバッチリ!
いかがでしたか?
「タスクの文字列を判定して、適切な制約タイプを流し込む」という仕組み(テンプレート化)が手に入れば、プロジェクトの初期セットアップや定例のスケジュールメンテにかかっていた膨大な時間が一瞬でゼロになります。
マクロの記録ボタンを押すだけのステージから、「オブジェクトをロジカルに制御する」エンジニアのステージへ。今回のコードをベースに、ぜひ皆さんの現場のルールに合わせたカスタムフィールド判定などを組み込んでみてください。
あなたのプロジェクト管理が、もっとスマートで創造的なものになりますように。それでは、次の極限の知見でお会いしましょう!
