Project VBAを掌握する極限の知見:リソース過負荷リアルタイム・モニタリングの構築
レガシーシステムの最前線に立つ我々にとって、Microsoft ProjectのVBA(Visual Basic for Applications)は、単なるマクロの域を超えた「制御インターフェース」である。プロジェクトマネジメントの現場において、リソースの過負荷(オーバーアロケーション)は、スケジュール崩壊の最大の火種となる。
今回は、プロジェクトファイルオープン時にイベントをフックし、全リソースの稼働率(Peak Units)をスキャン、閾値を超えた場合にWindows APIを活用したダイナミックな警告を発報する「リアルタイム・モニタリング・エンジン」の実装手法を解説する。
退屈なリファレンスの引き写しではない。オブジェクトのライフサイクルの深淵、メモリ管理の鉄則、そして実務に耐えうる堅牢性を備えたコードをここに提示する。
—
1. アーキテクチャの設計思想:なぜ「オープン時イベント」と「メモリ管理」が重要か
MS ProjectのVBA環境において、最も恐ろしいのは「COMオブジェクトの解放漏れによるメモリリーク」と「不正なコンテキストでのイベント実行によるクラッシュ」である。
リソースの稼働率を監視するためには、`Project_Open` イベントプロシージャを適切に利用し、ドキュメントのロード直後にメモリ上のリソースコレクションを走査する必要がある。この時、暗黙のオブジェクト参照や不適切な変数スコープを残すと、Projectプロセスの肥大化や、最悪の場合のデータ破損を招く。
シニアエンジニアたる者、以下の3点を厳守せよ。
1. 完全なオブジェクトの明示的解放 (`Nothing` 代入)
2. エラーハンドリングの網羅とトランザクション的思考
3. Windows APIを用いた非同期かつ視認性の高い警告UIの構築
—
2. 実装コード:リソース監視モニタリング・エンジン
以下のコードは、`ThisProject` モジュールおよび標準モジュールに配置することで、プロジェクトオープン時に自動稼働する。
① `ThisProject` モジュール(イベントフック)
Option Explicit
‘ =================================================================
‘ 1. Project Open イベントフック
‘ =================================================================
Private Sub Project_Open(ByVal ASG As Project)
On Error GoTo ErrorHandler
‘ 監視閾値(例: 100%超えを過負荷と判定)
Const OVER_ALLOCATION_THRESHOLD As Double = 1.0
‘ リソース監視プロシージャの呼び出し
Call MonitorResourceWorkload(ASG, OVER_ALLOCATION_THRESHOLD)
Exit Sub
ErrorHandler:
MsgBox “リソース監視モジュールで致命的なエラーが発生しました。” & vbCrLf & _
“Error: ” & Err.Description, vbCritical, “System Critical Error”
End Sub
② 標準モジュール(コアロジック&API連携)
Option Explicit
‘ Windows API: メッセージボックスに詳細なアイコンと挙動を付与するための宣言
If VBA7 Then
Private Declare PtrSafe Function MessageBoxW Lib “user32” ( _
ByVal hWnd As LongPtr, _
ByVal lpText As LongPtr, _
ByVal lpCaption As LongPtr, _
ByVal uType As Long) As Long
Else
Private Declare Function MessageBoxW Lib “user32” ( _
ByVal hWnd As Long, _
ByVal lpText As Long, _
ByVal lpCaption As Long, _
ByVal uType As Long) As Long
End If
Private Const MB_ICONWARNING As Long = &H30&
Private Const MB_OK As Long = &H0&
Private Const MB_SYSTEMMODAL As Long = &H1000&
‘ =================================================================
‘ 2. リソース稼働率スキャン & 評価エンジン
‘ =================================================================
Public Sub MonitorResourceWorkload(TargetProject As Project, Threshold As Double)
Dim rs As Resources
Dim r As Resource
Dim overAllocatedCount As Long
Dim reportMessage As String
overAllocatedCount = 0
reportMessage = “以下のリソースが過負荷状態(閾値: ” & CStr(Threshold 100) & “%)検知されました。” & vbCrLf & vbCrLf
‘ オブジェクトの参照取得(パフォーマンス最適化のため変数を経由)
Set rs = TargetProject.Resources
If rs Is Nothing Then Exit Sub
‘ リソースコレクションの高速走査
Dim i As Long
Dim totalResources As Long
totalResources = rs.Count
For i = 1 To totalResources
Set r = rs(i)
‘ 予約済みリソース(Costタイプ等)を除外し、Workタイプのみを対象にする
If r.Type = pjResourceTypeWork Then
‘ PeakUnits(ピーク稼働率)の評価
‘ MS Project内部では 1.0 = 100% として格納されている
If r.PeakUnits > Threshold Then
overAllocatedCount = overAllocatedCount + 1
reportMessage = reportMessage & “・ ” & r.Name & ” (ピーク稼働率: ” & Format(r.PeakUnits, “0%”) & “)” & vbCrLf
End If
End If
‘ ループ内での個別オブジェクト解放(メモリプレッシャーの軽減)
Set r = Nothing
Next i
‘ 閾値超過リソースが存在する場合のみ警告を発報
If overAllocatedCount > 0 Then
reportMessage = reportMessage & vbCrLf & “スケジュールを再調整してください。”
Call ShowNativeWarning(“リソース過負荷警告 – リアルタイムモニタ”, reportMessage)
End If
CleanUp:
‘ 【極めて重要】オブジェクト変数の完全解放
Set rs = Nothing
Set r = Nothing
Exit Sub
ErrorHandle:
Debug.Print “MonitorResourceWorkload Error: ” & Err.Description
Resume CleanUp
End Sub
‘ =================================================================
‘ 3. Windows API ラッパー(システムモーダル警告)
‘ =================================================================
Private Sub ShowNativeWarning(Title As String, Message As String)
Dim titlePtr As LongPtr
Dim msgPtr As LongPtr
‘ VBAのBSTRをUTF-16ポインタに変換してAPIへ直叩きする
‘ レガシー環境における文字化けと描画コストを極限まで排除
#If VBA7 Then
titlePtr = StrPtr(Title)
msgPtr = StrPtr(Message)
#Else
titlePtr = StrPtr(Title)
msgPtr = StrPtr(Message)
#If
‘ システムモーダルとして描画し、ユーザーに確実な認知を強制する
Call MessageBoxW(0, msgPtr, titlePtr, MB_ICONWARNING Or MB_OK Or MB_SYSTEMMODAL)
End Sub
—
3. チーフアーキテクトが解説するコードの急所
A. なぜ標準の `MsgBox` ではなく `MessageBoxW` なのか?
MS Projectが大容量のプロジェクトファイル(数千タスク、数百リソース)をロードした直後は、UIスレッドがビジー状態にある。標準の `MsgBox` を使用すると、描画遅延や背面のウィンドウへの埋もれが発生するリスクがある。
ここでは `user32.dll` の `MessageBoxW` を直接コールし、`MB_SYSTEMMODAL` フラグを付与することで、他のどのウィンドウよりも最前面に強制割り込みさせ、管理者の見落としを完全に封じている。
B. COMオブジェクトのライフサイクル管理
VBAのガベージコレクションは頼りにならない。特にProjectオブジェクトモデルは、`For Each` ループやコレクションの直接参照を雑に行うと、解放されない参照がメモリ上に残り続け、Projectプロセスのメモリリーク(Bloat)を引き起こす。
今回のコードでは、`For i = 1 To totalResources` というインデックスアクセスを採用し、ループの都度 `Set r = Nothing` を実行。プロシージャの最後でも `rs` と `r` を確実に初期化することで、長期稼働するエンタープライズ環境であってもメモリリークが絶対に起きない設計としている。
—
4. 現場への導入と運用上の注意点
1. セキュリティセンターの設定:
マクロ有効ドキュメント(`.mpp` / `.mpt`)として保存し、組織のセキュリティポリシーに合わせて信頼できる場所(Trusted Locations)に配置すること。
2. 拡張性:
このモニタリングロジックを拡張し、閾値を超えた瞬間にTeamsやSlackのWebAPIへJSONペイロードをPOSTする連携モジュールへと発展させることも容易である(WinINet APIまたはMSXML2.ServerXMLHTTPを使用)。
リソース管理は感情ではなく、厳密な数値とアーキテクチャによってのみ統御される。このコードをあなたのシステムに組み込み、破綻なきプロジェクト運営を実現せよ。
