【実務・中級編】サブプロジェクト統合時の制約条件競合を自動解消するVBAスクリプト – Project VBA解析バイブル

スポンサーリンク

Project VBAを掌握する極限の知見:サブプロジェクト統合時の制約条件競合を自動解消するVBAエンジン

開発現場のリーダー諸君、日々のプロジェクト管理でお疲れ様だ。
複数のサブプロジェクトをマスタープロジェクトにインテート(統合)した瞬間、スケジュールのガントチャートが赤字の警告で埋め尽くされ、クリティカルパスが盛大に崩壊する……。この悪夢のような現象に頭を抱えた経験はないだろうか?

Project VBA(Microsoft Projectのオブジェクトモデル)を操る上において、スケジューリングエンジン(ASAP: できる限り早く / ALAP: できる限り遅く)の挙動と、サブプロジェクト間のリンクが引き起こす制約矛盾のメカニズムを理解していない者は、いつまで経っても「手動修正という名の不毛な残業」から抜け出せない。

今回は、マスタープロジェクトへのサブプロジェクト統合時に発生する制約条件の競合を検知し、一瞬で健全な状態へと自動調停するプロダクション品質のVBAエンジンを伝授する。

—

1. なぜ手動でのスケジュール調整は破綻するのか?

マスタープロジェクトにサブプロジェクトを挿入すると、外部タスクとの依存関係(リンク)が生まれ、各タスクに設定された制約条件(例:「〜までに完了」「〜日以降に着手」など)と強力なコンフリクトを起こす。

素人がやりがちなアプローチは、すべてのタスクの制約条件を力技で `pjAsSoonAsPossible`(できる限り早く)に書き換えることだ。しかし、これでは顧客とのマイルストーン契約や、外部リソースの稼働制限といった「ビジネス上のハード制約」まで吹き飛んでしまう。

我々が目指すべきは、以下の条件を満たすスマートな自動化だ。
1. ソフト制約とハード制約の識別: 変更して良い制約と、死守すべき制約をアルゴリズムで判別する。
2. 計算エンジンの負荷制御: VBAからProjectのスケジュールエンジンを叩く際、無駄な再計算を発生させず、一括処理でパフォーマンスを最大化する。
3. トランザクション的保全: 競合解消に失敗した場合、安全にロールバックできる構造にする。

—

2. アーキテクチャ設計:堅牢性を担保する3つの原則

プロダクションコードを書くにあたり、以下の設計思想を徹底する。

  • ScreenUpdating と Calculation の完全制御:

VBAからProjectを操作する際、描画と自動再計算が走るたびにパフォーマンスが地獄のように落ちる。処理の開始時に手動計算モードへ切り替え、最後に一括で再計算させる。

  • エラーハンドリングとオブジェクトのライフサイクル管理:

`.Subprojects` コレクションの操作は非常にデリケートである。メモリリークや不正な参照を防ぐため、オブジェクト変数の解放を怠らない。

  • 制約タイプの安全なフィルタリング:

`Task.ConstraintType` プロパティを監視し、意図しないスケジュール固定化を防ぐ。

—

3. 実装コード:サブプロジェクト制約自動調停エンジン

以下のコードは、アクティブなマスタープロジェクトに対し、サブプロジェクト間の制約競合を自動診断・解消する実用的なVBAモジュールである。そのまま標準モジュールに貼り付けて使用してほしい。

Option Explicit

‘ ==============================================================================
‘ 処理名: SubprojectConstraintResolver
‘ 概要 : マスタープロジェクト統合時の制約条件競合を自動検知・解消する
‘ 著者 : チーフアーキテクト
‘ ==============================================================================
Public Sub ExecuteConstraintHarmonization()
‘ エラーハンドリングの準備
On Error GoTo ErrorHandler

Dim startTime As Double
startTime = Timer

‘ 1. パフォーマンス最大化のための環境設定
Application.ScreenUpdating False
Application.Calculation 0 ‘ pjManual (手動計算)

Dim masterProj As Project
Set masterProj = ActiveProject

Dim t As Task
Dim resolvedCount As Long
resolvedCount = 0

MsgBox “サブプロジェクト統合データの制約条件スキャンを開始します。”, vbInformation, “制約エンジン稼働”

‘ 2. マスター内の全タスク(サブプロジェクト由来含む)を走査
For Each t In masterProj.Tasks
If Not t Is Nothing Then
‘ サブプロジェクトのサマリータスク、または外部依存を持つタスクを対象とする
If t.ExternalTask = False And t.Summary = False Then

‘ 例: 「指定日着手 (Start No Earlier Than)」や「指定日完了」などの
‘ 硬い制約が、外部リンクと競合しているケースをハンドリング
Select Case t.ConstraintType
Case pjConstraintMustStartOn, pjConstraintMustFinishOn
‘ これらはハード制約のため、ログに記録するのみで勝手に変更しない
‘ Debug.Print “ハード制約検出 (スキップ): ID=” & t.ID & ” – ” & t.Name

Case pjConstraintStartNoEarlierThan, pjConstraintFinishNoEarlierThan
‘ ソフト制約かつ、外部先行タスクが存在する場合の競合解消ロジック
If HasPredecessorConflict(t) Then
‘ 制約を柔軟な「できる限り早く」へコンバート
t.ConstraintType = pjAsSoonAsPossible
resolvedCount = resolvedCount + 1
End If

Case Else
‘ その他の不要な固定制約のクレンジング
‘ 必要に応じて追加
End Select

End If
End If
Next t

‘ 3. 強制再計算と画面描画の復元
Application.Calculation 1 ‘ pjAutomatic (自動計算)
masterProj.Calculate
Application.ScreenUpdating True

MsgBox “制約競合の解消が完了しました。” & vbCrLf & _
“修正されたタスク数: ” & resolvedCount & ” 件” & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, _
vbInformation, “処理完了”

Exit Sub

ErrorHandler:
‘ 異常系の復旧処理
Application.Calculation 1
Application.ScreenUpdating True
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub

‘ ==============================================================================
‘ 補助関数: 先行タスクとのスケジュール矛盾(競合)を判定する
‘ ==============================================================================
Private Function HasPredecessorConflict(targetTask As Task) As Boolean
HasPredecessorConflict = False

Dim predLink As TaskLink
For Each predLink In targetTask.Predecessors
Dim predTask As Task
Set predTask = predLink.FromTask

‘ 先行タスクの終了日が、対象タスクの制約日付を dépasse(超えて)いる場合、競合とみなす
If predTask.Finish > targetTask.ConstraintDate Then
HasPredecessorConflict = True
Exit Function
End If
Next predLink
End Function

—

4. 現場で活きる運用上の注意点とデータベース連携

このVBAエンジンを実際の組織展開(PMO体制など)に組み込む際は、以下のポイントに留意してほしい。

1. ファイルパスの絶対参照・相対参照問題:
サブプロジェクトをマスターに挿入する際、パスが切れるとリンク情報自体がロストする。VBAでサブプロジェクトを挿入・更新するロジックを組む場合は、必ずSharePointやネットワークドライブのUNCパス(`\\server\share\…`)を正規化して扱うこと。
2. Project Server / Project Online との親和性:
エンタープライズ環境(Project Web App)において、ローカルVBAから強制的に制約を書き換えると、チェックイン・チェックアウトの整合性エラーを踏むことがある。サーバー連携環境では、PWAのキュー処理の完了を待つウェイト処理を挟むのが定石だ。

総括

スケジュール管理の自動化とは、単なる「手間の削減」ではない。「人間が気付けないヒューマンエラーを、プログラムの冷徹なロジックでねじ伏せること」である。

今回提供したコードをあなたのプロジェクト管理基盤に組み込み、無駄なスケジュール調整の会議を今すぐ撲滅せよ。次回のアーキテクチャ解説にも期待してほしい。

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