Project VBAの深淵:外部リソース単価管理によるコスト計算の最適化とアーキテクチャの真髄
Project VBA(Microsoft ProjectのVBA)に長年携わってきた者であれば、一度は直面する壁がある。「リソース単価の変動を、どうプロジェクト計画に追従させるか」という命題だ。
標準的なProjectのUIで単価を書き換えるのは、歴史的経緯(履歴管理の欠如)を無視した場当たり的な対処に過ぎない。真のエンジニアであれば、単価を「外部の信頼できるソース(Single Source of Truth)」から引き込み、計算ロジックをプロジェクトファイルから分離させるべきだ。
本稿では、レガシー環境におけるパフォーマンスを極限まで引き出す、リソース単価の動的同期メカニズムを解説する。
—
1. アーキテクチャ設計の指針
単価管理における最大の敵は「メモリリーク」と「I/Oのオーバーヘッド」である。Excelから単価を取得する際、安易に `GetObject` や `CreateObject` を乱用し、プロセスの残骸を残してはならない。
- 疎結合の原則: プロジェクトファイルは単価計算のロジックを持たず、計算結果(コスト)のみを保持する。
- メモリ管理: `Application.Quit` を呼ぶだけでは不十分だ。オブジェクトを `Nothing` にする順序を厳守し、Windows APIを用いてプロセスを監視するレベルの慎重さが求められる。
—
2. 実装:外部単価テーブルとの同期メカニズム
以下のコードは、単価管理用Excelから `Resource.StandardRate` を更新するルーチンだ。パフォーマンス向上のため、`ScreenUpdating` の停止は必須である。
‘ 必要なAPI定義(必要に応じてクラスモジュールへ配置)
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If
Sub SynchronizeResourceRates()
Dim xlApp As Object
Dim wb As Object
Dim ws As Object
Dim res As Resource
Dim rateDict As Object
‘ メモリ最適化:早期バインディングは避け、オブジェクトのライフサイクルを制御する
Set rateDict = CreateObject(“Scripting.Dictionary”)
On Error Resume Next
Set xlApp = GetObject(, “Excel.Application”)
If xlApp Is Nothing Then Set xlApp = CreateObject(“Excel.Application”)
On Error GoTo 0
Set wb = xlApp.Workbooks.Open(“C:\Path\To\ResourceRates.xlsx”, ReadOnly:=True)
Set ws = wb.Sheets(1)
‘ 高速化:Dictionaryにキャッシュを読み込む(I/Oを一度に完結させる)
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(-4162).Row ‘ xlUp
Dim i As Long
For i = 2 To lastRow
rateDict.Add ws.Cells(i, 1).Value, ws.Cells(i, 2).Value
Next i
‘ リソースの更新
For Each res In ActiveProject.Resources
If Not res Is Nothing Then
If rateDict.Exists(res.Name) Then
res.StandardRate = rateDict(res.Name)
End If
End If
Next res
‘ 厳格なメモリ解放
wb.Close False
Set ws = Nothing
Set wb = Nothing
Set xlApp = Nothing
Set rateDict = Nothing
MsgBox “コスト計算の同期が完了しました。”, vbInformation
End Sub
—
3. シニアエンジニアが意識すべき「隠れたコスト」
メモリの断片化とオブジェクト解放
`Set obj = Nothing` を書けば安心だと思ったら大間違いだ。Project VBAにおいて、COMオブジェクトの解放が遅延すると、巨大なプロジェクトファイルを開閉する際にGC(ガベージコレクション)が追いつかず、Project自体がクラッシュする。
特に大規模なエンタープライズ構成では、`DoEvents` を適切に配置し、スタックを解放するタイミングを制御することが、システム安定性の要となる。
データの整合性
単価変更が「いつ」有効になるかを管理するために、外部Excel側で「有効開始日」のカラムを用意することを推奨する。現在のProjectの `StatusDate` と比較し、条件に合致する単価のみを抽出するロジックを組むことで、未来のコスト試算も可能になる。
—
結論:コードは「資産」ではなく「負債」である
システム管理者の諸君、我々が書くコードは「資産」ではない。将来の誰かが保守に頭を抱える「負債」である。だからこそ、冗長な処理を削ぎ落とし、APIの挙動を理解し、メモリの最後の一バイトまで制御下に置く必要がある。
この「単価同期ツール」は、単なる自動化スクリプトではない。プロジェクトの収益性を可視化し、レガシーなProject VBAに現代的なCI/CDの思想を注入するための、最初の一歩である。
この知見が、君たちの現場の「負債」を「武器」に変える一助となれば幸いだ。健闘を祈る。
