【実務・中級編】【初心者向け】Project VBAで「タスクの開始日」を書き換える前に知るべき日付計算の落とし穴 – Project VBA解析バイブル

スポンサーリンク

Project VBAを掌握せよ:タスク開始日を「安易に書き換えてはいけない」理由

Project VBAの世界へようこそ。君が今、自動化しようとしているその「タスクの日付変更」、実は地雷原の上を歩いていることに気づいているか?

多くの初心者は、`Task.Start = “2023/10/01″` といった単純な代入で満足する。だが、そのコードが実務に投入された瞬間、スケジュールは崩壊し、ガントチャートは赤字の警告で埋め尽くされることになる。なぜなら、MS Projectの「日付」は、Excelのセルの値とは根本的に概念が異なるからだ。

今日は、現場で生き残るための「稼働日カレンダー」を考慮した、堅牢な日付操作の極意を伝授する。

1. なぜ DateAdd だけでは「破滅」するのか

VBAの標準関数である `DateAdd` を使って「3日後」を計算し、それを開始日に代入する。一見正しく見えるが、これこそが初心者が陥る最大の罠だ。

MS Projectには「カレンダー」という概念がある。土日祝日、あるいは会社固有の非稼働日をどう扱うか。`DateAdd` はこれらを知らない。君が「3日後」と指定した日が、たまたまプロジェクトカレンダー上の「休日」だったらどうなるか?

  • 自動スケジューリング機能との衝突: Projectのエンジンが「その日は休日だから、実質的な開始日は翌営業日だ」と判断し、君の書き換えた値を上書き(または強制修正)する。
  • 不整合の発生: 依存関係(リンク)が設定されている場合、一つのタスクを強引に書き換えることで、後続タスクの制約条件が壊れ、工数計算が狂う。

2. 稼働時間を考慮する「プロの作法」

Project VBAには、カレンダーを考慮して日付を計算するための専用メソッド `Project.Application.ActiveProject.Calendar.Period` 等が存在するが、もっと手軽かつ確実に「稼働日ベース」で計算する方法がある。

それは、「Projectのエンジンに計算させる」ことだ。無理にVBA側で計算して値を押し付けるのではなく、「期間(Duration)」と「カレンダー」という制約条件をセットし、再計算を促すのが最も堅牢な設計である。

現場で使うべき「安全な日付操作」コード

以下のコードは、単に日付を代入するのではなく、タスクの属性を正しく設定することで、Projectのスケジュールエンジンを味方につける手法だ。

Sub SetTaskStartDateSafely(t As Task, targetDate As Date)
‘ 【重要】手動スケジュールモードなら自動計算されないため、
‘ まずは自動スケジュールモードに設定することを推奨する
t.Manual = False

‘ プロジェクトの稼働カレンダーを取得し、指定日が稼働日かチェックする
‘ もし非稼働日なら、次の稼働日までスキップするロジックを噛ませるのがプロ
Dim projCalendar As Calendar
Set projCalendar = ActiveProject.Calendar

‘ 日付が休日でないか確認(簡易チェック)
If Not projCalendar.Working(targetDate) Then
‘ 次の稼働日を探す(このロジックは標準搭載のメソッドを活用せよ)
targetDate = projCalendar.Period(targetDate).Finish + 1
End If

‘ 値を代入する
‘ 注意:ここで「制約条件」が設定されているとエラーになるため、
‘ 一旦制約を「指定なし(As Soon As Possible)」に戻すのが定石
t.ConstraintType = pjNoConstraint
t.Start = targetDate

‘ 変更を反映させるための再計算
Application.Calculate
End Sub

3. 実務における「3つの鉄則」

現場でバグを出さないために、以下の設計指針を脳に刻んでおいてほしい。

1. 制約条件(Constraint)の管理:
`pjMustStartOn` などの制約をコードで安易に設定するな。これは将来のスケジュールの柔軟性を奪う「呪い」になる。原則は `pjNoConstraint` だ。
2. Application.Calculate のタイミング:
大量のタスクを一括更新する場合、ループのたびに `Calculate` を呼ぶとパフォーマンスが著しく低下する。更新処理の最後に一度だけ呼ぶか、必要に応じて `Application.Calculation = pjManual` を一時的に切り替えること。
3. データ連携の罠:
外部のExcelやデータベースから日付を取り込む際、日付型(Date)のシリアル値が正しく変換されているか?特に「時刻」の扱い(0:00開始か、8:00開始か)は、Projectの工数計算において「0.1日」のズレを生む。常に `Format(targetDate, “yyyy/mm/dd”)` で日付のみを取り出す癖をつけろ。

最後に:コードは「対話」である

MS Projectは、君が命令を下す対象ではなく、「スケジュールという最適化問題を解くパートナー」だ。

君の仕事は、タスクの開始日を力ずくで書き換えることではない。「開始日という制約」と「カレンダーというルール」をProjectに正しく入力し、あとの計算はエンジンに任せることだ。

この視点さえ持てば、君が書くVBAは、単なるマクロから「保守可能な資産」へと進化する。さあ、エディタを開いて、よりエレガントなコードを実装してくれ。期待している。

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