【実務・中級編】リソース割り当てと依存関係を同時に最適化する自動化ロジック – Project VBA解析バイブル

スポンサーリンク

【Project VBA極限論】リソース稼働と依存関係を同期させる「自動スケジューリング・エンジンの設計思想」

多くのVBAエンジニアが陥る罠がある。それは「タスクの開始日」を単なる日付データとして扱い、コード上で単純に加算・代入してしまうことだ。

プロジェクトマネジメントの本質は「リソースの有限性」にある。タスクの依存関係(先行タスク)とリソースの稼働限界(キャパシティ)を同時に解かなければ、それはただの「動かないスケジュール表」に過ぎない。

今日は、Project VBAにおいて、リソースの稼働状況を動的に参照し、依存関係を維持したまま開始日を最適化する「自動スケジューリング・エンジン」の極意を伝授する。

1. なぜ「力技のループ」が破綻するのか

初心者が書くコードの典型は、単純な`For Each`ループによる日付加算だ。しかし、これでは以下の致命的な問題が発生する。

  • カレンダーの非同期: 土日祝日やリソース個別の休暇を無視している。
  • クリティカルパスの無視: 依存タスクが遅延した際、後続タスクを再帰的に押し出すロジックがない。
  • リソース競合の放置: 同一リソースが同日に複数のタスクを抱える「オーバーアロケーション」を検知できない。

堅牢なシステムを作るには、タスクを単なる行データと見なすのではなく、「イベント駆動型のオブジェクト」として再定義する必要がある。

2. アーキテクチャの要諦:依存関係のグラフ構造化

タスクの依存関係を解くには、タスクを「ノード」とした有向グラフとして扱うのが正攻法だ。

実装の戦略

1. タスク・オブジェクト化: 各タスクをクラスモジュールとして定義し、依存先情報を保持させる。
2. 稼働管理テーブルの外部保持: 稼働状況はVBA内に持たせず、Excelの別シートまたは軽量なSQLiteへ逃がす。VBAのメモリ上に全情報を抱え込むのはリークの元だ。
3. 再帰的更新(Recursive Update): 先行タスクが確定した瞬間に、その依存関係を辿って後続の開始日を再計算する。

3. 実践コード:リソース稼働を考慮したスケジューリング

以下は、先行タスクの終了日とリソースの稼働状況をチェックし、最短開始日を算出するロジックの核となる部分だ。

‘ 【クラス:clsTask】
‘ タスクの依存関係とリソース負荷を管理する
Public TaskID As String
Public ResourceID As String
Public Duration As Long
Public PredecessorID As String
Public StartDate As Date

‘ 指定リソースの稼働状況をチェックし、開始日を決定するロジック
Public Function CalculateOptimalStart(ByVal lastTaskEndDate As Date) As Date
Dim candidateDate As Date
candidateDate = lastTaskEndDate + 1 ‘ 基本は先行タスクの翌日

‘ ここで稼働カレンダーやリソースの負荷状況をAPIまたはシートから取得
‘ 稼働不可日の場合はDateAddでスキップする
Do While IsWorkingDay(candidateDate) = False Or IsResourceBusy(ResourceID, candidateDate)
candidateDate = candidateDate + 1
Loop

CalculateOptimalStart = candidateDate
End Function

‘ 【標準モジュール:Engine】
‘ プロジェクト全体を再計算するドライバ
Public Sub RebuildSchedule()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(“WBS”)
Dim i As Long

‘ 依存関係順(トポロジカルソート済み)にループを回す
For i = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim currentTask As New clsTask
‘ プロパティセット処理…

‘ 先行タスクの終了日を取得し、最適開始日を算出
Dim prevDate As Date
prevDate = GetPredecessorEndDate(currentTask.PredecessorID)

ws.Cells(i, “D”).Value = currentTask.CalculateOptimalStart(prevDate)
Next i
End Sub

4. 堅牢性を高めるための注意点

1. データベース連携の最適化

Excelをデータベースとして使う場合、`Range.Value`への度重なるアクセスはパフォーマンスを著しく低下させる。「一括配列読み込み(Variant型の配列へ格納)」と「一括書き込み」を徹底すること。読み書きの回数を1/100に減らすだけで、処理速度は劇的に向上する。

2. 再計算のトリガー設計

全てのタスクを毎回全計算するのは非効率だ。「変更されたタスクID」を特定し、その配下の依存ツリーのみを再計算するロジック(差分更新)を実装せよ。これができるかどうかが、プロとアマの境界線である。

3. バグを生まないための「静的テスト」

依存関係のループ(AがBを待ち、BがAを待つような循環参照)は、実行時に必ずシステムをハングさせる。コードの先頭で「巡回検知アルゴリズム」を組み込み、循環参照が検出された瞬間にエラーを投げるガード節を設けること。

結論:エンジニアとしての矜持

Project VBAは、単なる自動化ツールではない。組織の「時間」を操る高度なシミュレーション・エンジンだ。

「コピペで動く」ことは最低条件に過ぎない。読み手がそのコードの裏側にある「なぜこの順序で計算するのか」という意図を汲み取れるよう、ロジックを磨き上げること。それが、伝説的な自動化エンジニアへの唯一の道である。

さあ、コードを書いてプロジェクトの停滞を解消せよ。君の書く一行が、チームの生産性を左右するのだから。

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