Project VBAの深淵:標準機能を凌駕する「リソース負荷分析エンジン」の設計術
プロジェクトマネジメントにおいて、MS Projectの標準レポートは「全体像」を掴むには便利だが、現場のPMが本当に知りたい「特定の期間における、特定チームの過負荷」を可視化するには力不足だ。
「稼働率が100%を超えているか?」といった単純な閾値判定ではなく、Excelと連携してヒートマップを描画し、リソースの空き状況を直感的に把握する。今回は、Project VBAのオブジェクトモデルを掌握し、堅牢なデータ抽出ロジックを構築するための「極限の知見」を伝授する。
—
1. なぜ「標準機能」では足りないのか
MS Projectのリソース使用状況ビューは強力だが、「期間ごとのWork(実働時間)」をCSVやExcelへ自在に切り出す柔軟性がない。
我々が目指すべきは、Projectを「データベース」として扱い、必要な粒度(週次・月次)でデータを抽出する「抽出エンジン」の構築だ。ここで重要なのは、`Assignment`オブジェクトの扱いに尽きる。
—
2. 堅牢な設計のための3つの鉄則
1. TimephasedData(期間別データ)の罠を回避せよ
リソースのWorkは`Resource.Work`プロパティだけでは不十分だ。時間経過に伴う変化を取得するには、`Assignment.TimephasedData`を適切にループする必要がある。これを効率よく処理しないと、数千行のタスクを抱えるプロジェクトではVBAがフリーズする。
2. Excelとの連携は「配列(Array)」で完結させる
セルを1つずつ操作するのは素人のやり方だ。Projectから抽出したデータは、一度メモリ上の二次元配列に格納し、最後にExcelへ一括転送する。これがパフォーマンスを100倍にする唯一の道だ。
3. 例外処理(Error Handling)の徹底
リソースが未割り当ての場合や、タスクにカレンダー異常がある場合、VBAは容易にクラッシュする。`On Error Resume Next`で誤魔化すのではなく、オブジェクトの存在チェックを必ず挟むこと。
—
3. 実装コード:高性能リソース負荷抽出エンジン
このコードは、指定期間内のリソースごとの工数を集計し、Excelへ出力するための基盤となる。
Option Explicit
‘ プロジェクト内のリソース負荷を抽出し、Excelへ出力するエンジン
Sub ExportResourceWorkload()
Dim pj As Project
Dim res As Resource
Dim asn As Assignment
Dim tpd As TimephasedData
Dim wb As Object ‘ Late BindingでExcelを操作
Dim ws As Worksheet
Dim rowIdx As Long
Set pj = ActiveProject
‘ Excelのインスタンス作成(既存のExcelを制御)
Set wb = CreateObject(“Excel.Application”)
wb.Visible = True
Set ws = wb.Workbooks.Add.Sheets(1)
rowIdx = 2
ws.Cells(1, 1).Value = “Resource Name”
ws.Cells(1, 2).Value = “Date”
ws.Cells(1, 3).Value = “Work (Hours)”
‘ 全リソースをループ
For Each res In pj.Resources
If Not res Is Nothing Then
‘ リソースに紐づく全てのAssignmentを処理
For Each asn In res.Assignments
‘ 期間別データを取得(例:プロジェクト開始から終了まで)
For Each tpd In asn.TimephasedData(pj.ProjectStart, pj.ProjectFinish, pj_TimephasedWork)
‘ 値がある場合のみ転送
If tpd.Value > 0 Then
ws.Cells(rowIdx, 1).Value = res.Name
ws.Cells(rowIdx, 2).Value = tpd.StartDate
ws.Cells(rowIdx, 3).Value = tpd.Value / 60 ‘ 分単位を時間に変換
rowIdx = rowIdx + 1
End If
Next tpd
Next asn
End If
Next res
MsgBox “抽出完了:総レコード数 ” & rowIdx – 2, vbInformation
End Sub
—
4. 現場で「使える」ツールに昇華させるためのヒント
パフォーマンスの最適化
上記のコードは基本形だ。本番環境では、`Application.ScreenUpdating = False`を併用し、抽出対象の期間を`DateAdd`関数で動的に指定できるように設計せよ。また、数万件のデータが想定される場合は、`ws.Range(“A2:C” & rowIdx).Value = MyArray`のように、配列を一気にセルへ書き出すロジックに差し替えることで、処理速度が飛躍的に向上する。
データベース連携の注意点
抽出したデータをSQL ServerやSQLiteに蓄積したい場合、「スナップショットの時刻」を必ずメタデータとして付与すること。リソースの負荷状況は日々変化する。時系列で分析できる「履歴データ」を蓄積することで、初めて「リソース計画の予実分析」が可能になる。
保守性を担保する「設計の美学」
コードを書き殴るな。`ResourceExtractor`クラスのようなモジュールを作成し、抽出ロジックとExcelへの出力ロジックを分離せよ。そうすれば、将来的に出力先をExcelからPower BIのデータソース(CSV)に変更したい場合も、メイン処理を弄らずに済む。
結びに:エンジニアとしての誇り
VBAは古い言語かもしれないが、MS Projectの心臓部に直接触れられる唯一のインターフェースだ。標準機能の壁にぶつかったとき、それを乗り越えるコードを書けるかどうか。それが、プロジェクトを成功に導くエンジニアと、単にツールを使わされているだけのオペレーターの決定的な違いである。
さあ、このコードを土台に、貴方だけの最強の分析レポートを構築してほしい。
