【実務・中級編】依存関係と制約条件の矛盾をVBAで検知する「整合性チェック」エンジンの開発 – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵へ:スケジュール矛盾を「殺す」整合性チェックエンジンの設計

プロジェクトマネジメントにおいて、VBAでスケジュール管理ツールを組むエンジニアが最も陥る罠、それは「計算の連鎖(Chain Reaction)」に無自覚であることだ。

ASAP(可能な限り早く)とALAP(可能な限り遅く)、そして固定制約(Start No Earlier Than等)。これらが複雑に絡み合うとき、VBAのロジックは往々にして無限ループや論理破綻を起こす。

今日は、場当たり的なif文の羅列で書かれた「動けばいいだけのコード」を卒業し、「矛盾を検知し、自ら是正を促すプロフェッショナルな整合性チェックエンジン」のアーキテクチャを伝授する。

—

1. なぜ「その場しのぎのチェック」では破綻するのか

多くの開発者は、タスクを更新するたびに「そのタスクだけ」を検証しようとする。これが間違いの元凶だ。

スケジュールとは「グラフ構造」である。先行タスク(Predecessor)の変更は、後続タスクの連鎖的な影響を引き起こす。この影響範囲(クリティカルパス)を特定せず、単一のセルだけを監視していても、プロジェクト全体の整合性は維持できない。

真の整合性チェックエンジンが備えるべき3つの要件:
1. 非再帰的な検証パス: スタックオーバーフローを防ぐためのキューベースの探索。
2. 制約違反の重み付け: 「警告(Warning)」と「致命的エラー(Critical)」の分離。
3. 副作用のない状態確認: データを書き換える前に「矛盾のシミュレーション」を行うサンドボックス的思考。

—

2. 整合性チェックエンジンの設計:コアコード

以下のコードは、タスクオブジェクトを走査し、「先行タスクの終了日 > 自タスクの開始日」という、最も基本的な依存関係の崩壊を検知するエンジンの骨格だ。

‘ プロジェクトタスク整合性チェッカー(コアエンジン)
‘ 依存関係と制約を検証し、矛盾がある場合はCollectionに格納する
Public Function ValidateSchedule(ByVal taskRange As Range) As Collection
Dim errors As New Collection
Dim cell As Range

‘ タスクIDをキーにした辞書でメモリ上に展開(セルアクセスを最小化するため)
Dim taskDict As Object
Set taskDict = CreateObject(“Scripting.Dictionary”)

‘ 1. メモリへのロード(パフォーマンスの要:セルの直接参照は遅い)
For Each cell In taskRange.Rows
‘ ID, StartDate, PredecessorID
taskDict.Add cell.Cells(1, 1).Value, Array(cell.Cells(1, 2).Value, cell.Cells(1, 3).Value)
Next cell

‘ 2. 矛盾検知ロジック
Dim taskId As Variant
For Each taskId In taskDict.Keys
Dim currentTask As Variant: currentTask = taskDict(taskId)
Dim preId As Variant: preId = currentTask(1)

If Not IsEmpty(preId) And taskDict.Exists(preId) Then
Dim preTask As Variant: preTask = taskDict(preId)

‘ 致命的な矛盾判定:先行タスクの終了日 > 自タスクの開始日
If preTask(0) > currentTask(0) Then
errors.Add “TaskID ” & taskId & ” は先行タスク ” & preId & ” の制約に違反しています。”
End If
End If
Next taskId

Set ValidateSchedule = errors
End Function

—

3. 実践:保守性とパフォーマンスを両立するコツ

① セルアクセスは「罪」である

VBAで最も高コストな操作は`Range.Value`へのアクセスだ。数千行のガントチャートをループで回す際、毎回シートを見に行けばツールはフリーズする。必ず一度配列(Array)またはDictionaryにデータを吸い上げ、メモリ上で処理せよ。

② データベース連携の注意点

外部のSQL ServerやAccessからデータを取得する場合、VBA側で計算するのではなく、できる限りSQLのWITH句(再帰CTE)で矛盾を検出した状態で取得するのが定石だ。VBAはあくまで「ユーザーへの警告表示」というインターフェースに徹するべきである。

③ エラーの「状態」を管理せよ

単にエラーを出すだけではツールは使い捨てになる。

  • Warning: 許容可能なスケジュール変更(余裕期間あり)
  • Critical: プロジェクト納期に直結する制約違反

この「重み」を定義し、条件付き書式と連動させてガントチャートを赤く染める。これが、現場の担当者が直感的に異常を検知できる「優れたUI」の正体だ。

—

4. チーフアーキテクトからのメッセージ

コードを書くとき、常に自問せよ。
「このロジックは、タスクが1万件になっても1秒以内に終わるか?」

VBAは、正しく設計すれば十分な高速性を発揮する。しかし、多くの開発者は「機能」を足すことばかりに夢中で、「計算の複雑性」を無視する。今回提示したメモリ展開の手法は、あらゆる大規模VBA開発の基礎となる。

このエンジンをあなたのツールに組み込め。そうすれば、ガントチャートの矛盾に頭を抱える時間は劇的に減り、あなたは本来集中すべき「プロジェクトの推進」にリソースを割くことができるようになるはずだ。

技術は、管理される側ではなく、管理する側にあるべきだ。健闘を祈る。

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