【実務・中級編】Taskの「実績開始日」と「実績終了日」をVBAで強制的に上書きする際の注意点 – Project VBA解析バイブル

スポンサーリンク

Project VBAの闇を制す:実績日付「強制上書き」の最適解と設計哲学

MS ProjectのVBAを扱う際、多くのエンジニアが「実績開始日(ActualStart)」と「実績終了日(ActualFinish)」の更新で壁にぶつかる。

「なぜ値を代入しても計算が戻されるのか?」
「なぜタスクのステータスが予期せぬ挙動を示すのか?」

これらは、Projectのエンジンが持つ「自動スケジュール計算ロジック」と「実績データの整合性チェック」という二重の制約を理解していないことに起因する。本稿では、このブラックボックスを解体し、現場で通用する堅牢な実装パターンを伝授する。

1. なぜ「単純な代入」は地雷なのか

Projectのタスクは、単なるDBのレコードではない。依存関係、カレンダー、制約条件が複雑に絡み合う「動的なオブジェクト」だ。

特に実績日付を直接操作しようとすると、Projectは「実績があるならば、そのタスクは進行中、あるいは完了しているはずだ」と判断し、`PercentComplete`や`ActualDuration`を勝手に再計算しようとする。ここで順序を誤れば、データは即座に不整合を起こし、スケジュール表は崩壊する。

鉄則:更新の黄金律

1. ステータスの確定: 実績日付を入れる前に、タスクの状態を明確にする。
2. 計算エンジンの制御: `Application.Calculation = pjManual` で一時的に自動計算を止めることは「推奨されない」。なぜなら、計算結果の整合性を自前で管理する必要が生じ、バグの温床になるからだ。
3. 適切なプロパティ順序: `ActualStart` → `ActualFinish` → `PercentComplete` の順で流し込むのが基本だ。

2. 実装コード:プロダクションレベルの堅牢性

以下は、外部データ(CSVやDB等)から実績を取り込む際に用いる、例外処理込みの標準実装である。

Public Sub UpdateTaskActuals(ByVal tsk As Task, ByVal actStart As Date, ByVal actFinish As Date)
On Error GoTo ErrorHandler

‘ 1. タスクがサマリータスクでないことを確認(サマリーは実績を直接更新不可)
If tsk.Summary Then Exit Sub

‘ 2. 実績開始日の反映
‘ 実績開始日を設定することで、Projectはタスクを「進行中」と認識する
If tsk.ActualStart <> actStart Then
tsk.ActualStart = actStart
End If

‘ 3. 実績終了日の反映
‘ 終了日を設定する前に、期間(ActualDuration)の整合性を考慮する必要がある
If actFinish <> #1/1/1984# Then ‘ 空日付判定
If tsk.ActualFinish <> actFinish Then
tsk.ActualFinish = actFinish
End If

‘ 4. 完了状態の明示(重要)
‘ 実績終了日を入れただけでは100%完了にならない場合がある
If tsk.PercentComplete < 100 Then tsk.PercentComplete = 100 End If End If Exit Sub ErrorHandler: Debug.Print "Error in TaskID " & tsk.ID & ": " & Err.Description ' ここでログ出力や例外処理を実装すること End Sub ---

3. 実務で「詰まない」ための設計ノウハウ

DB連携時の日付フォーマットの罠

Projectの`Date`型は、内部的に小数点を含む数値(シリアル値)で管理されている。データベース(特にSQL ServerやAccess)から取得した日付文字列をそのまま代入せず、必ず `CDate()` や `DateValue()` を通して型変換を行うこと。また、「0:00:00」という時刻データがスケジュールに与える影響を考慮し、必要であれば `DateAdd` で調整するロジックを挟むべきだ。

計算エンジンを止めない「賢い更新」

`Application.Calculation` を切る手法は、巨大なプロジェクトファイルではパフォーマンス面で有効だが、その代償として「依存関係の崩壊」というリスクを負う。
私は、「小さな粒度で逐次更新する」ことを推奨する。タスクごとに `Application.DoEvents` を挟みつつ、UIのフリーズを防ぎながら整合性を保つ手法だ。

リソース割り当てとの整合性

実績開始日を書き換える際、該当タスクにリソースが割り当てられているか確認してほしい。リソースが割り当てられていない状態で実績を強制書き込みすると、Projectは「誰がやったのか不明な実績」として内部的に警告を出すことがある。`tsk.Assignments` を走査し、必要に応じてダミーのリソースを割り当てる設計も検討すべきだ。

最後に:エンジニアへの提言

Project VBAは「自動化」のためのツールではない。「Projectのロジックと、現実の業務データの乖離を埋めるためのブリッジ」である。

コードを書く前に、まず「その更新が、プロジェクト全体のクリティカルパスをどう動かすか」をイメージしてほしい。それができる者だけが、真に保守性の高いシステムを構築できる。

もしあなたが「単に日付を入れ替えるだけのコード」で満足しているなら、それはまだ入り口に立ったに過ぎない。Projectという巨大な生命体の鼓動を感じながら、そのスケジュールを制御する。それが、我々自動化エンジニアの矜持だ。

タイトルとURLをコピーしました