Project VBAの深淵:リソース「作業輪郭(Work Contour)」を制御せよ
Project VBA(Microsoft ProjectのVBAオブジェクトモデル)の世界へようこそ。多くの開発者が「タスクの割り当て」までは自動化するが、その内訳である「作業輪郭(WorkContour)」の深淵に触れた途端、プロジェクトは迷宮入りする。
「なぜリソースを割り当てたのに、工数が均等に配置されないのか?」
「なぜ手動で設定したはずのカーブが、再計算で吹き飛ぶのか?」
今日は、VBAを用いて作業輪郭をプログラム制御し、実務で耐えうる「堅牢なリソース管理ツール」を構築するための設計思想を伝授する。
—
1. なぜ「作業輪郭」の制御が鬼門なのか
Projectの`Assignment`オブジェクトにおける`WorkContour`プロパティは、単なる数値ではない。これは「時系列データの生成ルール」だ。
一般的な開発者は、値を代入すれば勝手にグラフが描かれると勘違いする。だが、Projectは再計算(Recalculation)のたびに、タスクの期間とリソースの制約に基づいてこの輪郭を再評価する。
陥りがちなアンチパターン
- UIの即時更新を過信: `Application.Calculate`を多用して処理を重くする。
- コンター値の不整合: 期間(Duration)と作業量(Work)のバランスが崩れた状態で特定の輪郭(例:ベル型)を適用し、Project内部でエラー(計算不整合)を誘発させる。
これらを防ぐ唯一の道は、「輪郭適用前のバリデーション」と「オブジェクトの明示的な更新管理」だ。
—
2. 実装の設計思想:MVCをVBAで模倣する
リソース割り当てツールを構築する際、以下の3層構造を意識せよ。
1. Model (Data Layer): `Assignment`オブジェクトのプロパティを直接操作する。
2. Controller (Logic Layer): 輪郭(山型、谷型、前倒し等)の定数管理と計算ロジック。
3. View (UI Layer): ユーザーが視覚的に選択するVBAフォーム。
—
3. プロダクションコード:作業輪郭適用モジュール
以下は、選択中のタスクの割り当てに対し、指定したカーブを確実に適用する核心ロジックだ。
‘ ========================================================
‘ 目的: 作業輪郭を一括適用するメインエンジン
‘ 注意: 事前にタスクのWorkが0でないことを確認すること
‘ ========================================================
Public Sub ApplyWorkContourToSelection(contourType As PjWorkContour)
Dim tsk As Task
Dim asn As Assignment
‘ プロジェクトの再計算を抑制し、パフォーマンスを向上させる
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
For Each tsk In ActiveSelection.Tasks
If Not tsk Is Nothing Then
For Each asn In tsk.Assignments
‘ 輪郭を適用(pjContourBell, pjContourFrontLoaded等)
asn.WorkContour = contourType
‘ 重要: 変更を確定させるためにProject内部の計算プロセスを適宜同期させる
‘ 頻繁な呼び出しは避けるが、複雑な輪郭適用時は必須
asn.Update
Next asn
End If
Next tsk
CleanExit:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
このコードの肝
- `Application.ScreenUpdating`の制御: リソースが数千行あるプロジェクトでこれを怠ると、GUIの再描画だけで数分間フリーズする。
- `asn.Update`の活用: Projectの内部エンジンへ設定変更を通知する「トリガー」として機能させる。
—
4. 堅牢な運用のための3つの鉄則
① データベース連携の注意点
外部のExcelやSQL Serverからリソース負荷データを読み込む場合、「日付の粒度(Granularity)」に注意せよ。Projectの日付型は`Variant`だが、内部ではシリアル値で保持されている。外部データと突合する際は、必ず`DateValue()`等で日付のみを抽出して比較すること。
② 計算モードの強制管理
ツール実行中は、`Application.Calculation = pjManual` に設定し、最後に `pjAutomatic` に戻す設計を徹底せよ。自動計算が有効なままだと、1割り当てごとに再計算が走り、パフォーマンスが対数関数的に悪化する。
③ ユーザーへのフィードバック
長い処理を行う際は、`Application.StatusBar`に現在の進行状況を表示せよ。
Application.StatusBar = “タスクID: ” & tsk.ID & ” の輪郭を更新中…”
これがあるだけで、ユーザーは「フリーズした」と誤認して強制終了させることを防げる。
—
5. 最後に:プロフェッショナルであるために
あなたが作るのは単なるツールではない。プロジェクトマネージャーの「意思決定を支援するエンジン」だ。
「なぜこのタスクは山型(Bell)なのか?」「なぜここは前倒し(FrontLoaded)なのか?」
その背景にある工数戦略をコードに落とし込めるようになったとき、君は真のProject VBAエンジニアとして認められる。
このコードをコピーして終わりにするのではなく、ぜひ自社のプロジェクトの「リソースの癖」に合わせてロジックを磨き上げてほしい。健闘を祈る。
