MS Project VBAの深淵:依存関係の再帰的解析とメモリ管理の極意
プロジェクト管理の現場において、MS Projectの「先行タスク(Predecessors)」は、単なるプロパティではない。それはプロジェクトという有機体の血流であり、ボトルネックを特定するための神経系だ。
GUIで依存関係を追いかけるのは、数千行のコードをデバッガなしで読むに等しい。本稿では、Project VBAのオブジェクトモデルを掌握し、再帰処理を用いた依存関係の動的解析と、レガシー環境でも破綻しないメモリ管理の知見を伝授する。
—
1. Predecessorsの真実と解析の罠
MS Projectの `Task.Predecessors` プロパティは、文字列として返される。これをそのまま解析してはいけない。`TaskDependency` オブジェクトのコレクションを走査し、IDベースでリンクを追跡するのが正攻法だ。
ここでシニアエンジニアが意識すべきは「再帰によるスタックオーバーフローのリスク」と「オブジェクト参照の肥大化」である。
依存関係解析のコアロジック
以下は、特定のタスクから遡り、先行タスクを再帰的に抽出するエンジンの骨子だ。
‘ 依存関係解析のメインエンジン
‘ @param tsk: 解析対象のTaskオブジェクト
‘ @param depth: 再帰深度(無限ループ防止用)
Public Sub TracePredecessors(ByVal tsk As Task, ByVal depth As Integer)
If depth > 50 Then Exit Sub ‘ 安全装置:過度な再帰を制限
Dim dep As TaskDependency
Dim predecessorTask As Task
‘ TaskDependencyコレクションをイテレート
For Each dep In tsk.PredecessorTasks
Set predecessorTask = dep.FromTask
‘ ここでボトルネック判定ロジック等を挿入
Debug.Print Space(depth 2) & “-> ” & predecessorTask.Name & ” (ID: ” & predecessorTask.ID & “)”
‘ 再帰呼出し
TracePredecessors predecessorTask, depth + 1
Next dep
‘ メモリの明示的解放(オブジェクトのライフサイクル管理)
Set dep = Nothing
Set predecessorTask = Nothing
End Sub
—
2. メモリ最適化とVBAの「死角」
VBAのガーベジコレクションを過信してはならない。特に再帰処理を行う際、`Set` したオブジェクトを放置すれば、瞬く間にメモリリークを引き起こし、Projectのプロセスを不安定にさせる。
- 明示的解放の徹底: 再帰の各ステップで生成される `TaskDependency` や `Task` オブジェクトは、スコープを抜ける前に必ず `Set = Nothing` する。これは単なる作法ではなく、不安定なProject環境で数万行のタスクを捌くための「生存戦略」だ。
- Late Binding vs Early Binding: 開発時はEarly Binding(参照設定)で型定義を厳格化し、配布時はLate Binding(`CreateObject`)を検討せよ。環境依存によるDLL不整合を避けるのが、真のアーキテクトの矜持である。
—
3. レガシー環境を突き抜ける:APIとパフォーマンスの最適化
大規模プロジェクトでは、`Task.Predecessors` の解析中にUI更新が走るとパフォーマンスが劇的に低下する。これを回避するため、解析中は `Application.ScreenUpdating` を `False` にし、可能であれば `Windows API` を用いて、処理中に「応答なし」にならないようメッセージキューを制御する。
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If
‘ 処理中のUIフリーズを防ぐためのメッセージポンプ
Public Sub DoEventsSafe()
DoEvents
Sleep 1 ‘ わずかなウェイトでCPU負荷を抑制
End Sub
—
4. 視覚化へのアプローチ:データ構造の変換
解析した依存関係は、そのまま出力してはならない。JSONやCSV形式に変換し、外部の可視化ライブラリ(D3.jsなど)に渡すのが現代的な解だ。
1. 解析エンジン: 上記のVBAで依存関係をメモリ上にマップする。
2. シリアライズ: `Scripting.Dictionary` を使い、先行-後続のキー・バリューペアを作成する。
3. データ出力: `ADODB.Stream` を使用してUTF-8形式で書き出す(FileSystemObjectよりもI/O効率が良いため)。
アーキテクトの視点
タスクの依存関係を可視化するということは、「プロジェクトの時間の流れを逆回転させる」ことに他ならない。ボトルネックは常に、複雑に絡み合った依存関係の「結節点(クリティカルパスの合流点)」に潜んでいる。
このスクリプトを運用する諸君には、単にコードを動かすだけでなく、出力されたデータを基に「どの先行タスクが後続のクリティカルパスを阻害しているか」を読み解く洞察を期待する。
—
まとめ:極限を目指す者へ
Project VBAは古い技術だが、そのオブジェクトモデルは依然として強力だ。メモリを意識し、再帰の深さを制御し、OSの挙動を理解する。この3点を守れば、どんなに巨大なプロジェクトファイルも、君の掌の上で制御可能なデータへと変わるだろう。
次回の記事では、このデータを基にした「クリティカルパスの自動推論とリスク予測モデル」について深掘りする。準備はいいか。
