MS Project VBAを極める:リソース「単価レートテーブル」の動的切り替え自動化
プロジェクトマネジメントにおいて、コスト管理の精度はプロジェクトの成否を分ける生命線だ。しかし、標準機能のMS Projectでフェーズごとの単価変動(例えば、基本設計フェーズと実装フェーズでエンジニアの単価レートが変わるなど)を管理しようとすると、手動でのレートテーブル(A〜E)の書き換えという、ヒューマンエラーの温床となる非効率な作業に直面する。
今回は、Project VBAのオブジェクトモデルの裏側を知り尽くしたアーキテクトの視点から、リソースの「単価レートテーブル」をプロジェクトのフェーズや外部データに応じて一括で動的に切り替える運用自動化の極意を伝授する。
単なる「動くコード」の提示にとどまല്ല、実務の現場で絶対に破綻しない堅牢な設計思想を叩き込む。
—
1. なぜ「手動のレート切り替え」は現場を崩壊させるのか?
MS Projectには、1つのリソースに対して最大5つ(A〜E)の単価レートテーブルを持たせる機能がある。タスクの「コスト Rate Table」フィールドで指定することで、作業に応じた単価を適用できる。
しかし、大規模プロジェクトにおいて、数百人規模のリソースのレートテーブルをフェーズ移行のたびに手動で切り替えるのは狂気の沙汰だ。
- 履歴の追跡困難: どのフェーズでどのレートが適用されていたか監査できない。
- 更新漏れ: 新規追加されたリソースにレートが反映されず、コスト計算が狂う。
- メンテナンス性: 組織改編や単価改定があった際、ファイルを開いて手動修正するのは工数の無駄。
これを解決するのが、外部データ(Excel等)をソースとしたVBAによる一括動的切り替えエンジンである。
—
2. 堅牢な設計のためのアーキテクチャ方針
プロダクション環境でVBAを動かす場合、以下の3点を死守しなければならない。
1. トランザクション的思考(整合性の維持):
処理途中でエラーが発生した際、中途半端にレートが書き換わった状態を放置しない。エラーハンドリングを徹底し、必要に応じてロールバック(またはログ出力による即座の検知)を行う。
2. オブジェクトのライフサイクルとパフォーマンス:
MS ProjectのVBAにおいて、画面の再描画(ScreenUpdating)やイベントの発生は、処理速度を劇的に低下させる原因となる。一括処理時は必ずこれらを抑制する。
3. データ駆動型アプローチ:
ハードコーディングを排除し、どのリソースにどのレートテーブル(A〜E)を適用すべきかのマッピングをExcelなどの外部データ定義から動的に読み込ませる。
—
3. 実装コード:単価レートテーブル一括切り替えエンジン
以下のコードは、アクティブなプロジェクトに対し、指定したレートテーブル(例: “A”, “B”, “C”)を全リソース(または特定条件のリソース)に一括適用するプロシージャである。
実務ですぐに組み込めるよう、エラーハンドリングとパフォーマンス最適化を組み込んだプロダクションコードとして記述している。
‘ ==============================================================================
‘ モジュール名:
‘ 概要: リソースの単価レートテーブルを一括で動的に切り替えるプロシージャ
‘ アーキテクトノート: 画面描画の停止と厳格なエラーハンドリングにより、
‘ 大規模プロジェクトのパフォーマンス劣化とデータ破損を防ぐ。
‘ ==============================================================================
Public Sub ApplyDynamicRateTable(ByVal targetRateTable As String)
‘ 1. 変数宣言と事前検証
Dim r As Resource
Dim originalCalc As Long
‘ レートテーブルの入力値検証 (A〜Eのいずれかであること)
targetRateTable = UCase(Trim(targetRateTable))
If Not targetRateTable Like “[A-E]” Then
MsgBox “無効なレートテーブルが指定されました。「A」から「E」のいずれを指定してください。”, _
vbCritical, “レート切替エラー”
Exit Sub
End If
‘ 2. パフォーマンス最適化と安定性のための設定
‘ ※MS ProjectではAppliation.ScreenUpdatingに相当するものはないため、
‘ CalculationModeを手動にしてバックグラウンド計算を抑制する
originalCalc = Application.Calculation
Application.Calculation = pjCalcManual
On Error GoTo ErrorHandler
‘ 3. 処理開始のログ(イミディエイトウィンドウに出力)
Debug.Print “— レートテーブル切替処理開始: ” & Now & ” —”
Debug.Print “適用レートテーブル: ” & targetRateTable
‘ 4. リソースループによる一括適用
Dim updatedCount As Long
updatedCount = 0
For Each r In ActiveProject.Resources
‘ リソースが有効(名前が存在し、コストリソースやNullでない)かチェック
If Not r Is Nothing Then
If r.Name <> “” Then
‘ 標準単価レートテーブル(CostRateTable)プロパティを設定
‘ 注: 0=A, 1=B, 2=C, 3=D, 4=E に対応するEnum、または文字列指定が可能
Select Case targetRateTable
Case “A”: r.CostRateTable = pjCostsRateTableA
Case “B”: r.CostRateTable = pjCostsRateTableB
Case “C”: r.CostRateTable = pjCostsRateTableC
Case “D”: r.CostRateTable = pjCostsRateTableD
Case “E”: r.CostRateTable = pjCostsRateTableE
End Select
updatedCount = updatedCount + 1
End If
End If
Next r
‘ 5. 計算モードの復元とプロジェクトの再計算
Application.Calculation = originalCalc
‘ 変更を反映するために再計算を実行
CalculateAll
Debug.Print “— レートテーブル切替処理完了 (更新リソース数: ” & updatedCount & “) —”
MsgBox “リソースのレートテーブルを [” & targetRateTable & “] に正常に切り替えました。” & vbCrLf & _
“対象リソース数: ” & updatedCount, vbInformation, “処理成功”
Exit Sub
ErrorHandler:
‘ 6. 異常系ハンドリング
‘ 異常終了時も必ず計算モードを元に戻す
Application.Calculation = originalCalc
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
Debug.Print “!!! 異常終了: ” & Err.Description & ” (” & Err.Number & “) ” & Now & ” !!!”
End Sub
—
4. 現場で活きる!さらに高度な実務応用テクニック
上記のコードは「全リソースに同じレートテーブルを適用する」ものだが、実務では「フェーズやリソースグループ(社外・社内など)ごとに異なるレートテーブルを割り当てたい」という要求が必ず発生する。
その場合、以下のような設計アプローチをとるのがプロの流儀だ。
外部マスタ(Excel/CSV)との連携
VBA内部に条件をハードコーディングするのではなく、プロジェクトフォルダ内にあるマスタ定義ファイル(`RateMapping.xlsx`など)をADOや`Workbooks.Open`で読み込み、リソースの「テキストフィールド(Text1〜30など)」や「リソース名」をキーにして、対応する `CostRateTable` を動的にマッピングする。
‘ 概念コード例:リソース名とテーブルのマッピング適用
Dim dictRateMap As Object
Set dictRateMap = CreateObject(“Scripting.Dictionary”)
‘ … Excelから [リソース名 -> レート種別] の対応表をDictionaryに読み込む …
For Each r In ActiveProject.Resources
If dictRateMap.Exists(r.Name) Then
Select Case dictRateMap(r.Name)
Case “A”: r.CostRateTable = pjCostsRateTableA
‘ … 同様に B〜E を割り当て
End Select
End If
Next r
この「データ駆動型」の設計にしておけば、将来の単価改定や新しいフェーズの追加が発生した際も、VBAのコードを一切変更せず、Excel側の定義を修正するだけで対応可能になる。これが保守性の高い真の業務自動化システムである。
—
5. まとめ
Project VBAを用いたリソース管理の自動化は、単なる手間の削減ではない。「プロジェクト原価計算の精度担保」と「マネジメントの属人化排除」を同時に達成するための強力な武器だ。
今回紹介したパフォーマンス配慮の設計思想(計算モードの制御)と、エラーハンドリングの鉄則をベースに、あなたのプロジェクトにも「動的レート切り替えエンジン」を実装してほしい。プロジェクトリーダーとしての手腕が、コードの品質にそのまま現れるはずだ。
