【テクニカル・上級編】依存関係の「ラグタイム」を一括調整する実務ツール – Project VBA解析バイブル

スポンサーリンク

Project VBAを掌握せよ:タスク依存関係の「ラグタイム」を制する極限の自動化術

Project VBAの深淵に触れたことがある諸君なら知っているはずだ。GUI上のマウス操作でタスクの依存関係を一つ一つ調整することが、どれほど無益で、かつバグの温床となるかを。

特に「ラグタイム」の一括操作は、プロジェクトの遅延リスクをシミュレートする際に必須の武器となる。だが、MS Projectのオブジェクトモデルは、時としてメモリを食い荒らし、大規模な計画表では平然とハングアップを引き起こす。

本稿では、シニアエンジニアが現場で即座に展開できる、「ラグタイム一括最適化エンジン」の実装指針を授ける。

1. なぜ「標準機能」では足りないのか

Projectのタスクリンク(TaskDependencies)は、一見単純なコレクションに見える。しかし、内部的には複雑な再計算エンジンと紐付いており、単なるループ処理でラグタイムを書き換えるのは、データベースの整合性を自ら破壊する行為に等しい。

我々が目指すべきは、「メモリリークを皆無にし、再計算プロセスを最小化する」ことだ。VBAのガベージコレクションは信用するな。オブジェクトは自らの手で殺す(解放する)のが鉄則である。

2. 実装:ラグタイム一括調整ツール(Core Engine)

以下のコードは、全タスクのFS(終了-開始)関係に対し、指定したラグタイムを一括適用するプロシージャだ。

Option Explicit

‘ 依存関係の調整用メインモジュール
Public Sub BatchUpdateLagTime(ByVal targetLagDays As Double)
Dim proj As Project
Dim task As task
Dim link As taskDependency

Set proj = ActiveProject

‘ プロジェクトの再計算を抑制してパフォーマンスを最大化
Application.Calculation = pjManual

On Error GoTo Cleanup

For Each task In proj.Tasks
If Not task Is Nothing Then
For Each link In task.TaskDependencies
‘ 依存関係がFS(Finish-to-Start)の場合のみラグタイムを調整
If link.Type = pjFinishToStart Then
‘ ラグタイムはProject内部では「分」単位で保持される
‘ 1日 = 480分(環境により調整)
link.Lag = targetLagDays 480 & “m”
End If
Next link
End If
‘ メモリ解放の明示的介入(大規模プロジェクトでのGC安定化)
Set link = Nothing
Next task

Cleanup:
‘ 最後に再計算を実行し整合性を確保
Application.Calculation = pjAutomatic
Application.CalculateAll

Set task = Nothing
Set proj = Nothing

If Err.Number <> 0 Then
MsgBox “Critical Error: ” & Err.Description, vbCritical
End If
End Sub

3. シニアエンジニアのための最適化の知見

メモリとライフサイクル

上記のコードで `Set task = Nothing` をループ内で行うのは、VBAの参照カウンタを確実にデクリメントし、大規模なWBS(数千タスク)を扱う際のメモリスタック溢れを防止するためだ。`For Each` ループ内でオブジェクトが生成され続ける設計は、Project VBAにおいては死を意味する。

再計算の制御(Calculation Mode)

`Application.Calculation = pjManual` を使用せよ。これを怠ると、リンクを1つ書き換えるたびにProjectは全タスクのクリティカルパスを再計算しようと試みる。数千のリンクを持つファイルでこれをやれば、処理時間は指数関数的に増大する。変更を全てコミットした後に `CalculateAll` を叩くのが、プロの作法だ。

Windows APIによる「強制終了」の検知(応用編)

もし、非常に重いProjectファイルを扱うなら、Windows API `GetTickCount` や `Sleep` を利用して、処理中のUIフリーズを回避しつつ、タスクの進捗状況をステータスバーに表示させるべきだ。

‘ ステータスバー更新の定石
Application.StatusBar = “Processing Task ID: ” & task.ID
DoEvents ‘ UIスレッドを解放する

4. 現場への提言:レガシーとの共存

このスクリプトは、単なる便利ツールではない。プロジェクト管理における「仮説検証」のスピードを上げるためのツールだ。

  • リスク管理: 「もし納期が全工程で2日遅れたら?」というシミュレーションが数秒で終わる環境を構築せよ。
  • 保守性: 本コードは汎用性を高めるため、定数(480分)をプロジェクトの作業時間カレンダーから取得する関数へと拡張することを推奨する。

我々はツールに振り回される存在ではない。ツールを定義し、プロジェクトの複雑性を制御するアーキテクトである。このコードをベースに、諸君の現場における「最適解」を構築してほしい。

コードは嘘をつかない。だが、最適化の意識を欠いたコードは必ず現場を殺す。

次回の講義では、ProjectとExcel間での「差分同期」を、ADOを用いた高速化アプローチで深掘りする。期待しておけ。

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