【実務・中級編】VBAでタスクの「カスタムフィールド」を活用した依存関係の管理 – Project VBA解析バイブル

スポンサーリンク

プロジェクトの闇を切り裂く:Project VBAによる「動的依存関係」の極意

多くのエンジニアがMicrosoft Projectの標準機能である`Predecessors`(先行タスク)プロパティに翻弄されている。GUIでポチポチとリンクを貼る作業は、プロジェクトが100行を超えた瞬間に崩壊する。特に、外部システムやExcelと連携する際、標準の依存関係プロパティは「壊れやすく、可視化しにくい」という致命的な弱点を抱えている。

本稿では、標準機能に頼らず、「カスタムフィールドに依存先IDを埋め込み、プログラムで依存関係を再構築する」という、堅牢かつ柔軟なアーキテクチャを伝授する。これは小手先のテクニックではない。大規模プロジェクトを制御するための「設計思想」だ。

1. なぜ標準の「先行タスク」では不十分なのか

標準の`Task.Predecessors`は、内部的に文字列(例: “3FS-2days,5″)として保持される。これがなぜ危険なのか。

  • IDの流動性: 行の入れ替えやタスクの削除によって「ID」がズレる。
  • 整合性の欠如: GUIで誤操作された場合、その不整合を検知する術がない。
  • 外部連携の障壁: データベースからタスクをインポートする際、文字列パースのコストが肥大化する。

我々が目指すべきは、「依存関係の定義をデータ(カスタムフィールド)として保持し、レンダリング(リンク構築)は常にオンデマンドで行う」というステートレスなアプローチだ。

2. アーキテクチャの設計思想

以下のルールを徹底する。

1. ユニークIDの固定: MS Projectの`ID`ではなく、`Text1`等に外部システムと共通の「業務ユニークID」を持たせる。
2. 依存関係の正規化: `Text2`に「依存先ID」をカンマ区切りで格納する。
3. 再構築の原則: 実行のたびに一度すべてのリンク(TaskLinks)をクリアし、設定値に基づいて再構築する(冪等性の確保)。

3. 実装:堅牢な依存関係自動構築エンジン

以下は、この設計思想を具現化したプロダクションコードだ。

‘ プロジェクトの依存関係を再構築するメインエンジン
‘ 注意: 事前にすべてのタスクにText1(ユニークID)とText2(依存先ID)が設定されていること
Public Sub SyncDependencies()
Dim tsk As Task
Dim targetTsk As Task
Dim depId As Variant
Dim depIds() As String
Dim i As Long

‘ 1. 安全のために既存リンクを全削除(必要に応じて範囲を絞る)
‘ 注意: リンクを削除する際は、ActiveProject.TaskLinksのインデックスに注意
For i = ActiveProject.TaskLinks.Count To 1 Step -1
ActiveProject.TaskLinks(i).Delete
Next i

‘ 2. 各タスクのText2を読み取り、リンクを再構築
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
If Len(tsk.Text2) > 0 Then
depIds = Split(tsk.Text2, “,”)

For Each depId In depIds
‘ ユニークID(Text1)を検索してタスクを特定
Set targetTsk = FindTaskByCustomField(Trim(depId))

If Not targetTsk Is Nothing Then
‘ リンクを追加 (fs: Finish-to-Start)
ActiveProject.TaskLinks.Add Predecessor:=targetTsk, Successor:=tsk, LinkType:=pjFinishToStart
End If
Next depId
End If
End If
Next tsk

MsgBox “依存関係の再同期が完了しました。”, vbInformation
End Sub

‘ Text1からタスクを高速に見つけるためのヘルパー
Private Function FindTaskByCustomField(ByVal uniqueId As String) As Task
Dim tsk As Task
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
If tsk.Text1 = uniqueId Then
Set FindTaskByCustomField = tsk
Exit Function
End If
End If
Next tsk
End Function

4. プロダクション環境での重要事項

このコードを実務に投入する際、以下の3点だけは必ず担保せよ。

  • データバリデーション: `Text2`に存在しないIDが入力された場合、エラーハンドリングを入れ「どのタスクの依存関係が壊れているか」をログ出力する機能を実装すること。
  • パフォーマンスの罠: タスク数が増大した場合(500行以上)、`FindTaskByCustomField`のループ探索はボトルネックになる。その場合は、事前に `Dictionary` オブジェクトに `Text1` をキーとしてタスクをマッピングしておくキャッシュ戦略を推奨する。
  • トランザクション: リンク構築中に例外が発生すると中途半端な状態になる。`On Error GoTo` でエラー発生時にロールバック(あるいは警告メッセージ出力)を行う処理を忘れてはならない。

結論

依存関係をMS Projectの「標準機能」に委ねる時代は終わった。業務の根幹に関わるデータは、我々が定義した「カスタムフィールド」という安全地帯に隔離し、プログラムによって制御する。これこそが、大規模かつ複雑なプロジェクトを沈没させないための、エンジニアとしての矜持である。

さあ、コードを書き換え、不安定なプロジェクト管理から解放されろ。

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