【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は、単なる自動化ツールではない。組織の「時間」を操る高度なシミュレーション・エンジンだ。
「コピペで動く」ことは最低条件に過ぎない。読み手がそのコードの裏側にある「なぜこの順序で計算するのか」という意図を汲み取れるよう、ロジックを磨き上げること。それが、伝説的な自動化エンジニアへの唯一の道である。
さあ、コードを書いてプロジェクトの停滞を解消せよ。君の書く一行が、チームの生産性を左右するのだから。
