Project VBAの深淵:リソース情報を「割り当て」へ同期する極限の設計術
プロジェクトマネジメントにおいて、リソースの属性(スキルレベル、所属部署、単価ランク等)は、プロジェクト進行中に刻々と変化する。ここで多くのエンジニアが陥る罠がある。「リソースシートの情報を更新したのに、過去のタスク割り当て(Assignment)にそれが反映されていない」という不整合だ。
今回は、Project VBAの最深部、`Resource`オブジェクトと`Assignment`オブジェクトの「同期の不整合」を解消するアーキテクチャを伝授する。ただコードを動かすのではない。数千行のプロジェクトデータでも一瞬で同期し、かつ堅牢性を担保する「プロダクションレベル」のコードを設計する。
—
1. なぜ「力技のループ」では失敗するのか
多くの初心者は、`ActiveProject.Tasks`を全走査し、その中の`Assignments`をネストして回す。これは小規模プロジェクトなら動くが、数千の割り当てがある巨大計画では、VBAのCOMインターフェース呼び出しがボトルネックとなり、プロジェクトファイルを破壊するリスクすらある。
堅牢な同期のための3つの鉄則
1. 直接アクセスを避ける: オブジェクトを走査する際、可能な限り`Resource`側を起点にする。
2. 計算負荷を分離する: 更新対象外のAssignmentまで走査しない。リソースIDをキーにした辞書(Scripting.Dictionary)を構築し、メモリ上でマッピングを解決する。
3. エラーハンドリングの徹底: 割り当てがないリソースや、読み取り専用のカスタムフィールドに対する操作は、必ず`On Error Resume Next`を局所的に使い、例外を握りつぶさず適切にログへ落とす。
—
2. 実装コード:ResourceからAssignmentへの一括同期ツール
以下のコードは、リソースのカスタムフィールド(例: `Text1`)の値を、そのリソースが抱える全割り当てのカスタムフィールド(同`Text1`)へ強制同期するプロフェッショナル・テンプレートだ。
Option Explicit
‘ プロジェクト管理におけるリソース同期エンジン
Public Sub SyncResourceFieldToAssignments()
Dim prj As Project
Dim res As Resource
Dim asn As Assignment
Dim resDict As Object
Set prj = ActiveProject
‘ リソースのカスタム値を格納する辞書
Set resDict = CreateObject(“Scripting.Dictionary”)
‘ 1. リソース側の情報をメモリへキャッシュ(高速化の要)
For Each res In prj.Resources
If Not res Is Nothing Then
‘ Text1 を同期対象とする(実務に合わせて変更せよ)
resDict.Add res.ID, res.Text1
End If
Next res
‘ 2. 割り当て(Assignment)側の更新
Dim tsk As Task
On Error Resume Next ‘ 読み取り専用フィールド等の例外を回避
For Each tsk In prj.Tasks
If Not tsk Is Nothing Then
For Each asn In tsk.Assignments
If resDict.Exists(asn.ResourceID) Then
‘ 同期処理: AssignmentのText1をリソースのText1で上書き
If asn.Text1 <> resDict(asn.ResourceID) Then
asn.Text1 = resDict(asn.ResourceID)
End If
End If
Next asn
End If
Next tsk
On Error GoTo 0
MsgBox “同期完了: リソース情報が全割り当てへ適用されました。”, vbInformation
End Sub
—
3. 実務運用における注意点(コピペする前に読め)
1. 外部DB連携時のリスク
もしリソース情報をExcelやSQL Serverからインポートして運用している場合、`Resource.ID`は非常に不安定だ。プロジェクトを再保存するとIDが変わるケースがある。
- 対策: `Resource.UniqueID`をキーとして使用すること。これはプロジェクトのライフサイクルを通じて永続的である。
2. 再計算(Recalculation)の抑制
大規模プロジェクトでこのスクリプトを走らせると、`Application.Calculation`が自動再計算をトリガーし、1行更新するたびにプロジェクト全体のスケジュールが再計算され、処理が数分かかることがある。
- 対策: コードの冒頭で `Application.Calculation = pjManual` に設定し、最後に自動計算へ戻すことで、実行時間を数十分の一に短縮できる。
3. パフォーマンスの限界
数万件を超えるAssignmentを持つ場合、VBAのコレクション走査は限界を迎える。その場合はVBAではなく、Project Server API(PSI)またはMicrosoft Graph APIを用いた外部アプリケーションへ移行すべきだ。
—
最後に:エンジニアとしての矜持
VBAは「簡易的なスクリプト言語」と侮られがちだが、Projectにおいては「プロジェクトそのものを制御するオペレーティングシステム」に近い。
今回提示したコードは、単に値をコピーするだけではない。`Dictionary`オブジェクトを利用してオブジェクトモデルの走査を最小化し、`On Error`を戦略的に制御することで、どんな汚いプロジェクトデータが混入していてもフリーズさせない設計にしている。
君たちが手にするのは、ただのコードではない。「管理された混沌」を「秩序あるデータ」へ昇華させるためのツールだ。現場での成功を祈る。
