【実務・中級編】【中級者向け】WBSの階層構造を再帰関数で走査し、親タスクの進捗率を子タスクから自動計算する – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:再帰による進捗率自動集計の鉄則

MS ProjectのVBAを扱う諸君、ご苦労。
タスクの進捗管理において、「サマリータスクの進捗率を、配下の全子タスクから重み付け平均で算出したい」という要求は、自動化を志す者なら誰もが一度はぶつかる壁だ。

多くの駆け出しエンジニアは、`Task.OutlineChildren` をネストして力技で書こうとする。だが、プロジェクト規模が大きくなった途端、そのコードは重厚長大なスパゲッティと化し、計算の不整合という名のバグを撒き散らすことになる。

今回は、Projectのオブジェクトモデルを掌握し、再帰関数で「堅牢かつ美しい」進捗集計エンジンを実装する方法を伝授する。

1. なぜ「力技」は失敗するのか

まず肝に銘じてほしい。MS Projectのタスク構造は、常にフラットなリストとしてメモリ上に存在する。`OutlineLevel` というプロパティはあくまで「見た目の階層」を示しているに過ぎない。

ここで陥りがちな罠が以下の2点だ。

  • 計算順序の崩壊: 子タスクを更新する前に親タスクを計算してしまう。
  • 重み付けの無視: 全ての子タスクを「1つ」として数えてしまう(工数や期間を無視した単純平均は、プロジェクトマネジメントにおいて無価値だ)。

これらを解決する唯一無二の解法が、ボトムアップ式の再帰走査である。

2. 実装コード:堅牢な進捗集計エンジン

以下のコードは、単に計算するだけではない。プロジェクトの計算エンジン(Calculation Engine)と競合しないよう、更新が必要な箇所のみをピンポイントで叩く設計にしている。

‘ Project VBA: 階層的進捗自動計算エンジン
‘ 依存関係を考慮した重み付け平均(Durationベース)を算出する

Public Sub UpdateSummaryProgress()
Dim proj As Project
Set proj = ActiveProject

‘ プロジェクト全体を計算対象とする
‘ Calculation Engineを一時的に停止してパフォーマンスを向上させる
Application.Calculation = pjManual

‘ ルートレベル(階層レベル1)のタスクから再帰的に処理を開始
Call ProcessTask(proj.TaskGroups.Parent.Tasks)

Application.Calculation = pjAutomatic
MsgBox “進捗の集計が完了しました。”, vbInformation
End Sub

Private Sub ProcessTask(ByVal tasks As Tasks)
Dim t As Task

For Each t In tasks
‘ 子タスクを持つ(サマリータスク)場合
If t.OutlineChildren.Count > 0 Then
‘ まず子タスクを再帰的に処理(ボトムアップ)
Call ProcessTask(t.OutlineChildren)

‘ 子タスクの重み付け平均を算出
t.PercentComplete = CalculateWeightedProgress(t)
End If
Next t
End Sub

Private Function CalculateWeightedProgress(ByVal parentTask As Task) As Double
Dim child As Task
Dim totalDuration As Double
Dim totalProgress As Double

For Each child In parentTask.OutlineChildren
‘ 期間(Duration)を重みとして計算
‘ 期間が0の場合はタスクとして無視するなどのガード節を入れると堅牢性が増す
totalDuration = totalDuration + child.Duration
totalProgress = totalProgress + (child.PercentComplete child.Duration)
Next child

If totalDuration > 0 Then
CalculateWeightedProgress = totalProgress / totalDuration
Else
CalculateWeightedProgress = 0
End If
End Function

3. 実務で「生き残る」ための設計思想

このコードをそのまま現場に投入する際、いくつか守るべき「鉄則」がある。

① Calculation Engineの制御

`Application.Calculation = pjManual` を使え。これを行わないと、一つ進捗率を変えるたびにProject全体が再計算を走り、巨大なプロジェクトでは処理が数分止まる。プロのツールは「静かに」仕事をするものだ。

② データ型と浮動小数点

`PercentComplete` は `Double` 型だが、内部的には 0〜100 の値を持つ。計算過程で小数点以下の誤差が出ないよう、必要に応じて `Round` 関数を噛ませる配慮が必要だ。特にExcel等へエクスポートする予定があるなら、丸め処理は必須となる。

③ データベース連携の注意点

もしこのタスクデータをSQL ServerやSharePointに同期するなら、「計算済みフィールド」と「入力フィールド」を明確に分けろ
VBAで計算した結果を上書き保存し続けると、ユーザーが手動で微調整した進捗率が消失する。自動更新ロジックを走らせるなら、それ専用のフラグ(カスタムフィールド)を用意し、そこへ結果を吐き出すのが最も安全な運用だ。

4. 最後に:エンジニアとしての矜持

再帰関数は強力だが、デバッグが難しい側面もある。実装時は必ず小さなプロジェクトファイルでテストし、タスクの親子関係が複雑に絡み合ったケース(インデントを不自然に飛ばすなど)でも計算が破綻しないかを確認すること。

君たちが書くこのコードは、単なる自動化ツールではない。プロジェクトの現在地を正しく描き出す、経営判断のための「羅針盤」だ。

コードを書き終えたら、次は「なぜその重み付けが必要だったのか」をプロジェクトマネージャーに説明できるようになっておけ。それが、ただのコーダーと、真の業務自動化エンジニアを分かつ境界線だ。

健闘を祈る。

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