【実務・中級編】リソースの割り当てミスを検知するバリデーションチェックツール – Project VBA解析バイブル

スポンサーリンク

リソース管理の闇を断つ:Project VBAで構築する「最強の割り当てバリデーション・エンジン」

開発現場のPMやリソースマネージャー諸君。日々、ExcelやProject上でリソースの割り当て表とにらめっこし、「このタスク、本当にこのスキルセットのメンバーにアサインして大丈夫か?」「あいつ、今月すでに稼働率150%超えてるぞ…」と頭を抱えてはいないか?

属人化したチェックや、人間の目による目視監査は必ず破綻する。ヒューマンエラーを防ぐ唯一の手段は「機械による非情かつ正確なバリデーション」だ。

今回は、Microsoft ProjectのVBA(Visual Basic for Applications)を極限まで駆動させ、「リソースのスキル不一致」と「過剰割り当て(オーバーアロケーション)」をミリ秒単位で検知・リスト化する、プロダクション品質の監査ツールを授けよう。

—

なぜ「普通のVBAコード」では実務で使い物にならないのか?

世に溢れるVBAのサンプルコードの多くは、ただ動くだけの「おもちゃ」だ。数千行規模の大規模スケジュール(WBS)に適用した途端、以下の壁にぶつかる。

1. 画面描画の嵐による圧倒的なパフォーマンス低下
`ScreenUpdating` を制御せず、ループ内でオブジェクトを直接叩くため、数分待たされる。
2. リフレッシュされていないキャッシュの参照
Projectのオブジェクトモデルは、コストや稼働率の計算結果が非同期、あるいは即座に確定しないケースがある。正確なキャパシティを測るには、適切なプロパティとメソッドの順序が不可欠である。
3. エラーハンドリングの欠如
アサインされていないリソースや、カスタムフィールドの未定義による「実行時エラー 11(オーバーフロー)」や「オブジェクト変数がいません」の頻発。

これらを完全にクリアし、実務の現場で「秒速」で動く堅牢なアーキテクチャを構築する。

—

堅牢な設計思想:バリデーションの要件定義

今回作成するツール(`ResourceValidator`)は、以下の2点を自動監査する。

1. スキルマッチング検証
タスクのテキストフィールド(例: `Text1` に「Python」「VBA」「英語」などの要件)に対し、アサインされたリソースのロールやスキル(リソースのテキストフィールド等)が一致しているかを検証する。
2. 過剰割り当て(オーバーアロケーション)の検知
リソースの最大単位(Max Units)を超えたアサインメントが発生しているか、あるいはプロジェクト標準の稼働時間を逸脱していないかを数学的に弾き出す。

検知結果は、ダミーのメッセージボックスなどで終わらせない。監査専用の新しいExcelワークブックを自動生成し、そこに構造化されたログとして出力する。これがプロの仕事だ。

—

プロダクションコード:リソース監査エンジン

以下のコードを、Microsoft ProjectのVBAエディタ(標準モジュール)にそのまま貼り付けほしい。一切の妥協を排したエンタープライズ仕様だ。

Option Explicit

‘ ==============================================================================
‘ módulo名: icroResourceValidator
‘ 概要: リソースのスキルミスマッチおよび過剰割り当てを検知する監査エンジン
‘ 著者: Chief Enterprise Automation Architect
‘ ==============================================================================

Public Sub ExecuteResourceAudit()
Dim prj As Project
Set prj = ActiveProject

‘ パフォーマンス向上のための環境最適化
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.Calculation = pjCalculationManual

Dim tsk As Task
Dim asn As Assignment
Dim res As Resource

‘ 監査結果格納用配列(動的配列によるメモリ効率化)
Dim auditLogs() As String
Dim logCount As Long
logCount = 0

‘ 1. タスク単位のスキル不一致チェック
For Each tsk In prj.Tasks
If Not tsk Is Nothing Then
‘ サマリタスクや削除済みタスクは除外
If Not tsk.Summary And Not tsk.ExternalTask And tsk.Active Then

Dim requiredSkill As String
requiredSkill = Trim$(CStr(tsk.Text1)) ‘ Text1をスキル要件保持フィールドと仮定

If Len(requiredSkill) > 0 Then
For Each asn In tsk.Assignments
If Not asn.Resource Is Nothing Then
Set res = asn.Resource
Dim resourceSkill As String
resourceSkill = Trim$(CStr(res.Text1)) ‘ リソース側の保有スキル

‘ スキルが一致しない場合の検知ロジック
If InStr(1, resourceSkill, requiredSkill, vbTextCompare) = 0 Then
ReDim Preserve auditLogs(3, logCount)
auditLogs(0, logCount) = “スキルミスマッチ”
auditLogs(1, logCount) = tsk.ID
auditLogs(2, logCount) = tsk.Name
auditLogs(3, logCount) = “リソース [” & res.Name & “] のスキル (” & resourceSkill & “) が要件 (” & requiredSkill & “) に不適合”
logCount = logCount + 1
End If
End If
Next asn
End If

End If
End If
Next tsk

‘ 2. リソース単位の過剰割り当て(オーバーアロケーション)チェック
For Each res In prj.Resources
If Not res Is Nothing Then
If Not res.Null Then
‘ 稼働率(Units)の合計が最大キャパシティを超えているか判定
For Each asn In res.Assignments
If Not asn.Task Is Nothing Then
If asn.Task.Active And Not asn.Task.Summary Then
‘ アサインメント単位のユニット数がリソースの最大ユニットを超過している場合
If asn.Units > (res.MaxUnits 1) Then
ReDim Preserve auditLogs(3, logCount)
auditLogs(0, logCount) = “過剰割り当て”
auditLogs(1, logCount) = asn.Task.ID
auditLogs(2, logCount) = asn.Task.Name
auditLogs(3, logCount) = “リソース [” & res.Name & “] の負荷率が上限超過 (” & Format$(asn.Units, “Percent”) & “)”
logCount = logCount + 1
End If
End If
End If
Next asn
End If
End If
Next res

‘ 3. 監査結果をExcelに出力(データ連携のベストプラクティス)
If logCount > 0 Then
Call ExportLogsToExcel(auditLogs, logCount)
MsgBox “監査完了: ” & logCount & ” 件の警告事項が検出されました。Excelレポートを確認してください。”, vbExclamation, “リソース監査ツール”
Else
MsgBox “監査完了: 警告事項は検出されませんでした。リソース割り当ては健全です。”, vbInformation, “リソース監査ツール”
End If

CleanUp:
‘ 環境の復元
Application.ScreenUpdating = True
Application.Calculation = pjCalculationAutomatic
Exit Sub

ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
Resume CleanUp
End Sub

‘ ——————————————————————————
‘ 内部プロシージャ: 監査ログをExcelへ高速エクスポート
‘ ——————————————————————————
Private Sub ExportLogsToExcel(ByRef logs() As String, ByVal totalLogs As Long)
Dim xlApp As Object
Dim xlWb As Object
Dim xlWs As Object

‘ Excelインスタンスの遅延バインディング(バージョン依存エラーの回避)
Set xlApp = CreateObject(“Excel.Application”)
xlApp.Visible = True
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Sheets(1)
xlWs.Name = “Resource_Audit_Report”

‘ ヘッダーの設定
xlWs.Cells(1, 1).Value = “検出種別”
xlWs.Cells(1, 2).Value = “タスクID”
xlWs.Cells(1, 3).Value = “タスク名”
xlWs.Cells(1, 4).Value = “詳細メッセージ”

‘ ヘッダーの装飾
With xlWs.Range(“A1:D1”)
.Interior.Color = RGB(51, 51, 51)
.Font.Color = RGB(255, 255, 255)
.Font.Bold = True
End With

‘ 配列データを一括転送(セルへの個別アクセスを排除し爆速化)
‘ ※ 2次元配列の転送方向を調整するため、転置または1行ずつ書き込み
Dim i As Long
Dim outData() As Variant
ReDim outData(1 To totalLogs, 1 to 4)

For i = 0 To totalLogs – 1
outData(i + 1, 1) = logs(0, i)
outData(i + 1, 2) = logs(1, i)
outData(i + 1, 3) = logs(2, i)
outData(i + 1, 4) = logs(3, i)
Next i

xlWs.Range(xlWs.Cells(2, 1), xlWs.Cells(totalLogs + 1, 4)).Value = outData

‘ 罫線と列幅の自動調整
xlWs.Columns(“A:D”).AutoFit
With xlWs.Range(xlWs.Cells(1, 1), xlWs.Cells(totalLogs + 1, 4)).Borders
.LineStyle = 1 ‘ continuous
.Weight = 2 ‘ thin
.Color = RGB(200, 200, 200)
End With

Set xlWs = Nothing
Set xlWb = Nothing
Set xlApp = Nothing
End Sub

—

アーキテクチャの解説:プロが組み込んだ3つの技術的ポイント

1. 動的配列(`ReDim Preserve`)によるメモリ管理
エラー件数が事前に分からないため、ループ内でコレクションを回すのではなく、メモリ上で配列を拡張していく手法をとっている。これにより、オブジェクト生成のオーバーヘッドを最小限に抑えている。
2. Excel出力時の「一括転送(バルクインサート)」
VBAで最もやってはいけないのが、`For`ループの中で `ActiveCell.Value = …` とセルに直接書き込むことだ。このコードでは、一次元・二次元のバリアント配列(`outData`)にデータをすべてメモリ上で構築し、`Range.Value = outData` で一撃でExcelへ転送している。これにより、出力処理が数万行であっても一瞬で完了する。
3. 遅延バインディング(Late Binding)による環境耐性
Excel操作のオブジェクト生成に `CreateObject(“Excel.Application”)` を採用している。これにより、クライアント側のOfficeのバージョン違い(Excel 2016, 2019, 365など)による参照設定のミスマッチ(コンパイルエラー)を完全に予防している。

—

運用上の注意点とさらなる高みへ

このツールを現場に導入する際は、以下の運用ルールを徹底してほしい。

  • カスタムフィールドの運用統制

今回のコードでは、タスクの `Text1` をスキル要件、リソースの `Text1` を保有スキルとして定義している。現場の運用に合わせて、ここを `Enterprise Custom Field` の番号に書き換えて運用してほしい。

  • 定期実行(タイマー実行)の組み込み

週次定例の直前や、WBSのベースライン更新時にこのマクロを自動実行するトリガーを仕込んでおけば、「言った・言わない」「リソースが足りない」というプロジェクトマネジメントの最も醜い炎上を防ぐ強力な盾となる。

属人性に頼ったマネジメントは今日で終わりだ。コードでプロジェクトをコントロールし、真に価値のあるエンジニアリングに集中しよう。

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