【テクニカル・上級編】【上級者向け】依存関係の「複雑度」をスコアリング:リンクが多すぎるタスクを自動抽出する品質管理ツール – Project VBA解析バイブル

スポンサーリンク

依存関係の「複雑度」をスコアリング:リンクが多すぎるタスクを自動抽出する品質管理ツール

プロジェクトマネジメントにおいて、WBS(Work Breakdown Structure)のタスク間依存関係(Predecessors / Successor)は、計画の整合性を担保する生命線である。しかし、現場の泥臭いプロジェクトが進むにつれて、このネットワークはしばしば「スパゲッティ状態」と化す。

特定のタスクに無数の先行・後続タスクが集中すると、何が起きるか。一つの仕様変更がドミノ倒しのように全日程を崩壊させ、クリティカルパスの特定を絶望的に困難にする。いわゆる「高結合・低凝集」のアンチパターンが、スケジュール管理の世界でひそかに進行しているのだ。

今回は、Project VBA(Microsoft Projectのオブジェクトモデル)を極限までドライに駆動させ、タスクのリンク数を数学的にスコアリングし、計画破綻のリスクを抱えた「地雷タスク」を自動抽出する品質管理エンジンの実装を解説する。

—

1. Project VBAにおけるパフォーマンスの罠と設計思想

MS Projectのオブジェクトモデルは、Excel VBAのそれに比べて極めて「重い」。何千行ものタスクに対して `Task.Predecessors` や `Task.Successors` コレクションを安易にループさせると、COMのマーシャリングオーバーヘッドにより、実行時間が数分単位に膨れ上がる。

シニアアーキテクトが守るべき鉄則は以下の3点だ。

1. 画面描画の完全な凍結:`Application.ScreenUpdating = False` は必須。さらに `CalculationManual` に切り替え、無駄な再計算を排除する。
2. オブジェクトの明示的解放:VBAのガベージコレクションは頼りにならない。特にProjectのコレクション操作後は、変数に `Nothing` を代入してメモリリークを防ぐ。
3. コレクションの遅延バインディングとインデックスアクセス:`.Count` プロパティの多用を避け、メモリ上で高速に評価できるプロパティを直に叩く。

—

2. 依存関係複雑度スコアリングのアルゴリズム

タスク $T$ の複雑度 $C(T)$ を算出するため、単純なリンク数の総和だけでなく、先行・後続の方向性も考慮した重み付けを行う。

$$C(T) = (N_{\text{pred}} \times W_1) + (N_{\text{succ}} \times W_2)$$

  • $N_{\text{pred}}$: 先行タスク数(Predecessors)
  • $N_{\text{succ}}$: 後続タスク数(Successors)
  • $W_1, W_2$: 重み係数(通常は 1.0 だが、ボトルネックになりやすい後続タスク側を高めに設定することもある)

このスコアが閾値(例: 5以上)を超えたタスクを「高リスク・スパゲッティタスク」と判定し、ログ出力およびタスクの色分け(ハイライト)を自動で行う。

—

3. 実装コード:WBS品質管理・依存関係監査エンジン

以下のコードは、現在のプロジェクト計画をスキャンし、依存関係が過剰なタスクを検出してレポートを出力する実用的なVBAモジュールである。

Option Explicit

‘ —————————————————————–
‘ módulo: ModDependencyAudit
‘ 概要 : タスクの依存関係(先行・後続)をスキャンし、複雑度をスコアリングする
‘ 著者 : チーフアーキテクト
‘ —————————————————————–

Public Sub AuditTaskDependencies()
‘ パフォーマンスとメモリ保護のための定数・変数宣言
Dim prj As Project
Set prj = ActiveProject

Dim tsk As Task
Dim predCount As Long
Dim succCount As Long
Dim complexityScore As Double

‘ 閾値設定(この値を超えるリンクを持つタスクを警告対象とする)
Const THRESHOLD_SCORE As Double = 6.0
Const WEIGHT_PRED As Double = 1.0
Const WEIGHT_SUCC As Double = 1.2

Dim warningCount As Long
warningCount = 0

‘ 【極限最適化】画面描画と自動計算を停止し、COM往復のコストを最小化する
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.Calculation = pjCalculationManual

‘ 監査結果出力用の新しいレポート用カスタム数値フィールド(例: Number1)を活用
‘ 事前にプロジェクト側で「依存度スコア」等の名前で拡張フィールドを設定しておく想定

Dim logOutput As String
logOutput = “— タスク依存関係 複雑度監査レポート —” & vbCrLf

‘ タスクループの開始
For Each tsk in prj.Tasks
‘ サマリタスク(プロジェクトや要約行)およびマイルストーン、削除済みタスクを除外
If Not tsk Is Nothing Then
If Not tsk.Summary And tsk.Active Then

‘ 先行・後続タスクの数を安全に取得
‘ ※エラートラップを入れることでリンク切れや不正な参照を回避
On Error Resume Next
predCount = tsk.Predecessors.Count
succCount = tsk.Successors.Count
On Error GoTo ErrorHandler

‘ スコアリング計算
complexityScore = (predCount WEIGHT_PRED) + (succCount WEIGHT_SUCC)

‘ カスタムフィールド(Number1)にスコアを書き込み(後続のビューフィルタ用)
tsk.Number1 = complexityScore

‘ 閾値を超えた場合の処理(品質アラート)
If complexityScore >= THRESHOLD_SCORE Then
warningCount = warningCount + 1

‘ ガントチャート上で視覚的に目立たせる(背景色を赤紫系にハイライト)
tsk.TaskFont Color:=pjMaroon, Bold:=True

‘ ログ蓄積
logOutput = logOutput & “[” & tsk.ID & “] ” & tsk.Name & _
” (先行: ” & predCount & “, 後続: ” & succCount & _
“) => スコア: ” & complexityScore & vbCrLf
Else
‘ 正常なタスクはフォントをデフォルトに戻す
tsk.TaskFontReset
End If

End If
End If
Next tsk

‘ 処理結果の通知
Application.ScreenUpdating = True
Application.Calculation = pjCalculationAutomatic

If warningCount > 0 Then
MsgBox “監査完了: 依存関係が過剰なタスクが ” & warningCount & ” 件検出されました。” & vbCrLf & _
“該当タスクのフォントが赤色に変更され、Number1フィールドにスコアが記録されました。”, _
vbExclamation, “WBS品質管理システム”

‘ イミディエイトウィンドウに詳細出力
Debug.Print logOutput
Else
MsgBox “監査完了: 計画の依存関係は健全な範囲内に収まっています。”, vbInformation, “WBS品質管理システム”
End If

CleanUp:
‘ 【メモリ最適化】オブジェクト参照の確実な解放
Set tsk = Nothing
Set prj = Nothing
Exit Sub

ErrorHandler:
‘ 異常終了時の環境復元
Application.ScreenUpdating = True
Application.Calculation = pjCalculationAutomatic
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub

—

4. コードの深層解説:なぜこの実装なのか

1. 例外を孕む `.Predecessors.Count` の安全なハンドリング

Project VBAにおいて、存在しないリンクや参照整合性が崩れたタスクに対してコレクションのプロパティを叩くと、容赦なくランタイムエラー(エラー 1100など)が発生する。ここでは局所的に `On Error Resume Next` を挟むことで、レガシーなWBSファイル特有の「壊れたリンク」を踏んでもマクロが途中でクラッシュしない堅牢性を担保している。

2. ガントチャートへの即時フィードバック

検出されたタスクを単にログに出すだけでは、現場のプロジェクトマネージャーには響かない。`tsk.TaskFont Color:=pjMaroon, Bold:=True` を用いて、ガントチャート上の該当タスクを物理的に赤色に染め上げる。さらに、ユーザー定義フィールド(`Number1`)にスコアを永続化させることで、MS Project標準のフィルタ機能を用いて「スコア >= 6」のタスクだけを瞬時にフィルタリング表示させることが可能になる。

3. トランザクション的な環境復元

大規模なWBSを走査中にエラーが発生した場合、`ScreenUpdating = False` や `Calculation = pjCalculationManual` が解除されないままになると、ユーザーはMS Projectがフリーズしたと錯覚する。`ErrorHandler` ラベルを確実に通過させる構造にすることで、システム安全性を極限まで高めている。

—

5. シニアエンジニアからの実務的提言

このツールを導入しただけでは、プロジェクトの品質は良くならない。真の目的は、「なぜそのタスクにリンクが集中しているのか」を構造的に分析することだ。

大抵の場合、リンクが過剰なタスクの正体は以下のいずれかである。

  • 「何でも屋」タスク:1つの作業が完了しないと次の工程に進めないという、過剰に直列化された悪しき習慣。
  • マイルストーンの置き換え忘れ:成果物単位ではなく、担当者単位で細かくリンクを繋ぎすぎた結果のアカウンタビリティの迷子。

依存関係の複雑度を定量的(スコア)に可視化し、定期的にバッチ処理あるいはイベンガーとして走らせることで、プロジェクトの「腐敗」を未然に防ぐ。これこそが、アーキテクトがVBAコードを通じて現場にもたらすべき真のガバナンスである。

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