MS Project VBAの深淵:依存関係を「壊さず」タスクを置換する極限のアルゴリズム
MS ProjectのVBAを扱う際、多くのエンジニアが「Taskの削除」で挫折する。単純に`Task.Delete`を呼ぶだけで済むのは、依存関係が一切ないお遊びレベルのプロジェクトだけだ。
実務レベルのプロジェクトでタスクを削除すれば、当然ながら後続タスクとのリンクは切断され、クリティカルパスは崩壊する。「タスクを削除しても、依存関係を再接続してスケジュールを維持する」。これが、真に堅牢なプロジェクト管理自動化の第一歩だ。
今日は、Projectのオブジェクトモデルを掌握し、スケジュールの整合性を担保する「リンク再接続アルゴリズム」を伝授する。
—
1. なぜ「単純な削除」が罪なのか
Taskオブジェクトを削除すると、そのタスクを先行タスク(Predecessor)としていたすべての後続タスク(Successor)とのリンクが物理的に消失する。
- クリティカルパスの喪失: 依存関係が途切れることで、プロジェクト終了日が正しく計算されなくなる。
- 不整合の蓄積: 手動で再接続を繰り返せば、必ず人的ミスが発生する。
この問題を解決するには、「削除対象の先行タスクを、削除対象の『先行タスク』で上書きする」というバイパス構造を構築する必要がある。
—
2. 依存関係を維持する「バイパス・リコネクト」アルゴリズム
以下のコードは、特定のタスクを削除する前に、その「先行タスク」を「後続タスク」に引き継ぐためのプロダクション・グレードの関数だ。
‘ @description 指定タスクを削除し、先行タスクを後続タスクに継承させる
‘ @param targetTask 削除対象のTaskオブジェクト
Public Sub DeleteTaskWithLinkRedirection(ByVal targetTask As Task)
Dim predecessors As TaskLinks
Dim successors As TaskLinks
Dim predLink As TaskLink
Dim succLink As TaskLink
Dim succTask As Task
Set predecessors = targetTask.PredecessorTasks
Set successors = targetTask.SuccessorTasks
‘ 1. 後続タスクに対し、現在の先行タスクを再接続する(バイパス構築)
For Each succLink In targetTask.TaskLinks
If succLink.LinkType = pjSuccessor Then
Set succTask = succLink.ToTask
‘ 削除対象の先行タスクを、後続タスクに引き継ぐ
For Each predLink In predecessors
succTask.PredecessorTasks.Add predLink.PredecessorTask, predLink.LinkType, predLink.Lag
Next predLink
End If
Next succLink
‘ 2. 整合性を確認した上で削除を実行
targetTask.Delete
End Sub
このコードの設計思想
- 非破壊的な置換: 直接リンクを書き換えるのではなく、まず後続タスクに先行タスクをコピーし、その後で削除を行う。
- ラグとリンクタイプの継承: `predLink.Lag`や`LinkType`をそのまま引き継ぐことで、クリティカルパスの変動を最小限に抑える。
—
3. データベース連携とパフォーマンスの罠
プロジェクト管理ツールを開発する際、ExcelやSQL Serverと連携するケースが多い。ここで陥りやすい罠が「再計算コスト」だ。
- Application.Calculation = pjManual:
大量のタスクを一括操作する場合、都度発生する再計算(スケジューリング)はパフォーマンスを劇的に落とす。ループ処理の前後で計算モードを制御せよ。
- IDの変動に注意:
`Task.ID`は削除によって動的に変化する。ループ処理中にIDを直接参照するのは自殺行為だ。常に`Task.UniqueID`を使用し、オブジェクトへの参照を保持し続ける設計を徹底すること。
—
4. チーフアーキテクトからの忠告
VBAは強力だが、MS Projectのオブジェクトモデルは非常に繊細だ。以下の3点を守れ。
1. エラーハンドリングの徹底: `On Error Resume Next`で誤魔化すな。`TaskLinks.Add`に失敗した場合は、即座にトランザクションをロールバックする構造が必要だ。
2. イベントの制御: `Application.Calculation`を手動に設定した場合、処理終了後に必ず自動に戻せ。これを忘れると、ユーザーは「Projectがバグった」と誤解する。
3. 「なぜ」をコードに刻め: なぜそのリンクを引き継ぐのか。どのような制約条件下でそのロジックが必要なのか。コードコメントに設計意図を残せ。
—
結論:自動化は「責任」である
単にタスクを削除して楽をするのではない。「プロジェクトの整合性を維持し、常に最新のクリティカルパスを可視化する」という責任を、コードに肩代わりさせるのだ。
あなたが書くその10行のコードが、数千行のプロジェクト計画を救う可能性がある。これこそが、業務自動化エンジニアの真骨頂だ。さあ、今すぐ自身のプロジェクトでこのロジックを試し、依存関係の海をコントロールしてみせろ。
