プロジェクトVBAの深淵:カレンダー制御による「納期ズレ」を根絶するアーキテクチャ
プロジェクト管理において、VBAでWBS(タスク階層)を自動生成する際、多くの初学者が陥る罠がある。それは「カレンダーを無視した単純加算」だ。
「今日から5日後」が常に「5営業日後」とは限らない。祝日、休暇、あるいは特定のタスクだけが持つ特殊な稼働日設定。これらを無視した自動計算は、プロジェクトの開始直後に崩壊する砂上の楼閣だ。
今日は、Project VBAを使いこなし、稼働日ベースの依存関係を制御する「堅牢なエンジン」の設計思想を伝授する。
—
1. なぜ「単純加算」は死を招くのか
多くのコードが `Date + 5` という記述でタスク終了日を算出している。これはExcelの基本機能としては正しいが、プロジェクト管理としては「悪」だ。
プロジェクトには、以下の2つのカレンダー層が存在する。
- プロジェクト標準カレンダー: プロジェクト全体で共有される稼働日設定。
- タスク固有カレンダー: 特定の作業(例:海外拠点や特殊機材)に依存する個別の稼働日設定。
これらを `Project.Calendar` オブジェクトを介して制御しなければ、どれほど複雑なWBS構造を構築しても、結局は手動修正という「自動化の敗北」を迎えることになる。
—
2. 稼働日計算を掌握する設計思想
VBAでプロジェクトの依存関係を構築する際、重要なのは「日付を自分で計算しない」ことだ。Projectの持つ `Task.Finish` プロパティを直接操作するのではなく、`Task.Start` を設定し、`Duration` を与えることで、Projectのエンジンに計算させるのが鉄則である。
堅牢な実装のためのチェックリスト
1. カレンダーの存在確認: カレンダー名が誤っている場合、黙って標準カレンダーに戻るようなフォールバック処理を入れる。
2. 依存関係の可視化: `Task.TaskDependencies.Add` を使用し、親子関係と先行タスクを明確にする。
3. 計算の同期: プロジェクトの計算モードが `pjManual` であっても、更新時には `Application.CalculateAll` を呼び出し、不整合を防ぐ。
—
3. 実践:カレンダーを考慮したタスク追加コード
以下は、指定したカレンダー設定に基づき、稼働日を正しく計算してタスクを配置する実用的なコードだ。
‘ @brief 特定カレンダーを適用したタスク追加エンジン
‘ @param parentTask 親となるタスク
‘ @param taskName タスク名
‘ @param durationDays 稼働日数(文字列)
‘ @param calendarName カレンダー名
Public Sub AddTaskWithCalendar(ByRef parentTask As Task, _
ByVal taskName As String, _
ByVal durationDays As String, _
ByVal calendarName As String)
Dim newTask As Task
‘ 1. タスクの生成(親タスクの直下に作成)
Set newTask = parentTask.OutlineChildren.Add(taskName)
‘ 2. カレンダーの適用(存在チェックを伴う堅牢な設定)
On Error Resume Next
Dim cal As Calendar
Set cal = ActiveProject.Calendars(calendarName)
If Err.Number <> 0 Then
Debug.Print “Warning: Calendar ‘” & calendarName & “‘ not found. Using Base Calendar.”
Set cal = ActiveProject.BaseCalendars(1)
End If
On Error GoTo 0
newTask.Calendar = cal
‘ 3. 期間の設定(これによりProjectエンジンが稼働日計算を行う)
newTask.Duration = durationDays
‘ 4. 自動計算のトリガー
‘ 大規模なWBS構築時はループの最後で一度だけ実行すること
Application.CalculateAll
End Sub
—
4. 運用上の注意点とアーキテクトからの助言
データベース連携の罠
外部のデータベース(SQL ServerやExcelシート)からカレンダー情報を読み込む際、「文字列の揺らぎ」が最大の敵となる。「標準カレンダー」と「標準」が混在するだけでエラーは起きる。カレンダー名は必ずIDで管理するか、マスタテーブルによる正規化を徹底せよ。
パフォーマンスの極意
`Application.CalculateAll` は非常に重いメソッドだ。1,000行を超えるWBSを一気に作成する場合、ループ内で毎回計算させてはならない。
- `Application.Calculation = pjManual` に設定し、すべてのタスクを追加した後に `pjAutomatic` へ戻し、一度だけ計算を走らせる。これがプロの速度だ。
—
最後に:自動化の真髄
「コードを書いて終わり」ではない。あなたが作った自動化ツールが、現場のプロジェクトマネージャーの「思考の邪魔」をしていないか常に自問自答することだ。
カレンダーを制御するということは、プロジェクトの時間を制御することに他ならない。この技術を身につければ、あなたは単なるVBA使いではなく、プロジェクトの運行を設計するアーキテクトへと進化できる。
さあ、次はどんな非効率をコードで殲滅しようか?
