プロジェクトマネジメントの墓場から脱出せよ:MS Project VBAで「サマリータスク依存関係」を自動展開する極意
プロジェクト現場で最も恐ろしいのは、「サマリータスク(要約タスク)にリンクを張ったから、配下も当然連動するだろう」という甘美な勘違いだ。
MS Projectにおいて、サマリータスクへの依存関係設定は、プロジェクト全体のWBS(Work Breakdown Structure)を歪ませるトリガーとなり得る。実務レベルで「真に自動化されたスケジュール管理」を実現したいなら、サマリータスクのリンクを、その配下の全サブタスクに対して「論理的に整合する形で」再帰的に反映させる機構を自前で実装する必要がある。
今日は、中途半端な自動化でプロジェクトを死なせないための、堅牢かつ攻撃的なVBA実装を伝授する。
—
なぜ「手動」や「GUI操作」では限界があるのか
MS Projectの仕様上、サマリータスクは単なる「コンテナ」に過ぎない。ここに依存関係(FSリンク等)を設定しても、配下のタスクの開始日・終了日が自動計算で押し出される際、予期せぬクリティカルパスの分断や、リンクのデッドロックを招くことが多い。
我々が求めるのは、「親にリンクが張られた瞬間、その子の末端タスク(リーフノード)に対して、妥当な依存関係を再帰的に自動挿入する」というロジックだ。
堅牢な設計のための3つの鉄則
1. 再帰的探索の最小化: `Task.OutlineLevel` を活用し、無駄なループを回さない。
2. リンクの重複排除: 既に存在するリンクを重複生成しないこと。これを怠ると、MS Projectのメモリ消費は跳ね上がり、最悪の場合はファイル破損を招く。
3. Undo(元に戻す)の意識: VBA操作はProjectのUndoスタックを汚す。重要な操作の前には必ず `Application.Calculation = pjManual` を挟み、計算コストを制御せよ。
—
実装コード:Recursive Task Linker
以下のコードは、選択したサマリータスクを起点に、その配下にある全てのリーフタスクを抽出し、指定した先行タスクとの依存関係を再帰的に適用する。
‘ ———————————————————
‘ サマリータスク配下への依存関係一括展開ツール
‘ 前提: 選択したタスクを「親」、引数で渡されたタスクを「先行タスク」とする
‘ ———————————————————
Sub ApplyRecursiveLinks(parentTask As Task, predecessorTask As Task)
Dim subTask As Task
‘ 手動計算モードでパフォーマンスを最適化
Application.Calculation = pjManual
On Error GoTo ErrorHandler
‘ 配下のタスクを再帰的に走査
For Each subTask In parentTask.OutlineChildren
‘ サブタスクがさらに親なら、再帰的に潜る
If subTask.OutlineChildren.Count > 0 Then
ApplyRecursiveLinks subTask, predecessorTask
Else
‘ リーフノードにのみリンクを適用(重複チェック含む)
Call CreateLinkIfNotExist(subTask, predecessorTask)
End If
Next subTask
CleanExit:
Application.Calculation = pjAutomatic
Exit Sub
ErrorHandler:
MsgBox “Error: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
‘ リンクの重複を防ぐ堅牢なラッパー関数
Private Sub CreateLinkIfNotExist(targetTask As Task, predTask As Task)
Dim link As TaskLink
‘ 既に同じ先行タスクとリンクされているか確認
For Each link In targetTask.PredecessorTasks
If link.PredecessorTask.ID = predTask.ID Then Exit Sub
Next link
‘ リンク生成 (FS: Finish-to-Start)
targetTask.PredecessorTasks.Add Predecessor:=predTask, Type:=pjFinishToStart
End Sub
—
プロダクション環境での運用の注意点
1. 外部DB連携時のリスク管理
ProjectのデータをExcelやSQL Serverへエクスポートする際、この「自動生成されたリンク」は非常に強力な武器になる。しかし、「誰がどのリンクを生成したか」というメタデータをカスタムフィールド(Flag1~20など)に記録しておくことを強く推奨する。自動ツールが生成したリンクを、後の工程で手動修正した際、その変更を上書きして戻してしまう「自動化の暴走」を防ぐためだ。
2. パフォーマンスの真実
MS Projectのオブジェクトモデルは、アクセスするたびに内部で再計算フラグが立つ。数千行規模のWBSでこのツールを走らせる場合は、`Application.ScreenUpdating = False` を必ず使用し、GUIの描画を停止せよ。これだけで実行速度は3倍~5倍に跳ね上がる。
3. 「なぜ」をコードに残せ
VBAはメンテナンス性が低いと断罪されがちだが、それはコードのせいではない。コメントに「なぜこのリンクが必要なのか」の論理を記していないからだ。このコードは単なるリンク生成器ではなく、プロジェクトの依存関係を強制する「ガードレール」であるという意識で運用してほしい。
最後に:エンジニアとしての矜持
自動化ツールを作ると、必ず「なぜ今の運用を変える必要があるのか?」と現場から突き上げられる。その時はこう言い返せ。
「手作業で行っている依存関係の調整は、プロジェクト終了時に必ず負債として跳ね返ってくる。私はその負債を、今、ここで処理しているだけだ」
このツールが、あなたのプロジェクトを混沌から救う一助となれば幸いだ。健闘を祈る。
