Project VBAを掌握する:ベースラインの「局所更新」という禁断の術
プロジェクトマネジメントにおいて、ベースラインは「聖域」である。一度刻まれた計画を安易に書き換えることは、進捗管理の死を意味する。しかし、大規模プロジェクトにおける現実の現場では、特定のWBS階層や、特定フェーズのみを最新計画へ追従させる「部分更新」の需要が必ず発生する。
標準機能の「ベースラインの保存」は全体を塗りつぶすが、我々アーキテクトに求められるのは、「特定のタスクグループのみを対象とした精密なスナップショット」を制御することだ。
今日は、Project VBAの深淵に触れ、オブジェクトモデルの挙動を完全に制御する極限のテクニックを伝授する。
—
1. なぜ「標準機能」では足りないのか
Projectの `BaselineSave` メソッドは強力だが、プロジェクト全体を対象とするか、選択範囲に依存する。しかし、API経由で厳密に制御する場合、UIの状態(選択範囲)に依存するコードは「脆弱性」の温床となる。
我々が目指すべきは、「特定のフラグ(例:Flag1)が立っているタスクのみを、指定したベースライン(例:Baseline1)に書き込む」という、UIに依存しない疎結合な処理だ。
—
2. 実装:メモリ効率を最大化したタスク更新ロジック
ここで重要なのは、オブジェクトの走査において `Task` オブジェクトを無駄に生成・破棄しないこと、そして `Application.ScreenUpdating` を用いて描画処理を完全に止めることだ。
Option Explicit
‘ 伝説的なエンジニアは、常にオブジェクトのメモリリークを警戒する
‘ プロジェクトの巨大なタスクツリーを走査する際の最適化手法
Public Sub UpdatePartialBaseline(ByVal targetBaseline As PjBaselines)
Dim proj As Project
Set proj = ActiveProject
‘ 描画と再計算を停止し、処理速度を限界まで引き上げる
Application.ScreenUpdating = False
Application.Calculation = pjManual
Dim t As Task
Dim selectedTasks As Tasks
‘ 必要なタスクのみを抽出してコレクション化
‘ 大規模プロジェクトでは、全タスクのループはキャッシュミスを招く
Set selectedTasks = proj.Tasks
On Error GoTo Cleanup
For Each t In selectedTasks
‘ 特定のタスクグループ(ここではFlag1がTrueのもの)のみを対象とする
If Not t Is Nothing Then
If t.Flag1 = True Then
‘ Taskオブジェクト個別のベースライン保存はサポートされていないため
‘ 一時的にそのタスクを選択状態に見せかけ、Saveを実行する
‘ ※現実的には「個別のBaselineSave」は存在しないため、
‘ 運用上はカスタムフィールドへの値退避が推奨されるが、
‘ ここではAPIの限界を突く手法として示す。
Call ProcessSingleTaskBaseline(t, targetBaseline)
End If
End If
Next t
Cleanup:
‘ 明示的なオブジェクト解放
Set t = Nothing
Set selectedTasks = Nothing
‘ 環境を復元
Application.Calculation = pjAutomatic
Application.ScreenUpdating = True
End Sub
Private Sub ProcessSingleTaskBaseline(ByRef t As Task, ByVal bl As PjBaselines)
‘ ここに個別のベースライン更新ロジックを実装する
‘ 実務では、カスタムフィールドへ現在のStart/Finishを書き戻す方が
‘ ベースラインの整合性を保てるケースが多い
t.Text1 = t.Start
t.Text2 = t.Finish
‘ 以下、必要に応じて値を設定
End Sub
—
3. アーキテクトの視点:なぜ「カスタムフィールド」を使うのか
勘の鋭い読者なら気づいたはずだ。Projectの標準ベースライン機能は「プロジェクト単位」の設計思想で作られている。APIで無理やり部分的なベースラインを操作しようとすると、後々「ベースラインの整合性チェック」でシステムがエラーを吐くリスクがある。
真のプロは、標準機能を破壊しない。
特定のタスクグループを更新したいならば、以下のアーキテクチャを採用すべきだ。
1. 影のベースライン(Shadow Baseline): `Text1` や `Start1` といったカスタムフィールドを、いわゆる「中間計画用スナップショット」として定義する。
2. データの同期: マクロで、特定の条件(Flag1 = True)に該当するタスクの `Start` と `Finish` を、`Start1` / `Finish1` にコピーする。
3. 比較ロジック: ガントチャート上の比較表示は、これらのカスタムフィールドを参照するように設定する。
この手法ならば、`BaselineSave` という重いAPIを叩くことなく、計算負荷を最小限に抑えつつ、意図したタスクグループのみの計画管理が可能になる。
—
4. 結び:極限の現場で生き残るために
VBAはレガシーと言われる。しかし、Projectの内部データ構造を直接操作し、数万行のタスクを数秒で最適化できる力は、モダンなWeb APIでは代替できない。
オブジェクトを生成したら必ず `Set Nothing` で解放し、`ScreenUpdating` を殺し、再計算をマニュアルモードにする。これらの「当たり前」を徹底するだけで、あなたのツールは数千人のプロジェクトエンジニアを支える「インフラ」へと昇華する。
次は、Windows APIを用いた「プロジェクトファイル保存時の競合チェックと排他制御」について深掘りしよう。システム間連携において、ここを疎かにする者はプロとは呼べない。
健闘を祈る。
