【Project VBAの深淵】タスクIDの「流動性」を制する者だけが、真のプロジェクト自動化を成し遂げる
Project VBA(MS Projectのオブジェクトモデル)を扱う際、中級者からシニアへとステップアップする最大の壁が「ID」と「UniqueID」の乖離だ。多くの開発者が、タスクの並び替え(ソート)や行削除によって「ID」が再割り当てされるという初歩的な罠に陥り、リンク設定(先行タスク・後続タスク)を破壊してプロジェクトを崩壊させる。
今日は、MS Projectにおけるオブジェクトのライフサイクルと、メモリ消費を最小限に抑えた「整合性担保の極限ロジック」を伝授する。
—
1. なぜ「ID」に頼ってはいけないのか
MS ProjectのUI上に見えている「ID」は、単なる表示用のインデックスに過ぎない。行を挿入すればIDは繰り上がり、フィルタリングやソートを行えばその順序は瞬時に変化する。
一方で、「UniqueID」はタスク生成時に付与される不変の識別子だ。プロジェクトの全期間を通じて一意であり、データベース的な整合性を保つための唯一の鍵となる。
鉄則:ロジック内では常に `UniqueID` でタスクを特定し、操作の直前のみ `ID` へ変換せよ。
—
2. 整合性を維持する「リンク生成エンジン」の設計
以下は、`UniqueID` をキーにしてリンクを張るための堅牢なルーチンだ。タスクオブジェクトを頻繁に参照するとメモリリークやオーバヘッドの原因となるため、`ActiveProject` へのアクセス回数を最小化するのがアーキテクトの作法である。
‘ 依存関係をUniqueIDで確実に設定するためのラッパー関数
Public Sub SetDependencyByUniqueID(ByRef proj As Project, _
ByVal predecessorUniqueID As Long, _
ByVal successorUniqueID As Long, _
Optional ByVal linkType As PjTaskLinkType = pjFinishToStart)
Dim predTask As Task
Dim succTask As Task
‘ UniqueIDでタスクオブジェクトを直接取得
‘ IDでの検索は行わず、オブジェクトモデルのFindを回避する
Set predTask = proj.Tasks.UniqueID(predecessorUniqueID)
Set succTask = proj.Tasks.UniqueID(successorUniqueID)
If Not predTask Is Nothing And Not succTask Is Nothing Then
‘ リンク生成:TaskLinksコレクションに直接追加
‘ 重複チェック等のバリデーションをここに実装すべきである
succTask.TaskLinks.Add Name:=predTask, LinkType:=linkType
Else
Debug.Print “Error: Task not found. PredUID=” & predecessorUniqueID & ” SuccUID=” & successorUniqueID
End If
‘ メモリ最適化:明示的な解放(VBAにおいては重要)
Set predTask = Nothing
Set succTask = Nothing
End Sub
—
3. レガシー環境におけるパフォーマンス最適化:メモリの呪縛を解く
大規模プロジェクト(数千タスク規模)では、`Tasks` コレクションへのループアクセスが致命的なボトルネックとなる。特に、プロパティをループ内で何度も叩くと、MS ProjectのCOMレイヤーとVBAのブリッジ間で膨大なマーシャリングが発生する。
極限の知見:オブジェクトのキャッシュと解放
1. オブジェクトの変数保持: `Tasks(i)` をループ内で繰り返すな。一度変数に格納し、必要なプロパティを抽出し終えたら即座に解放する。
2. API利用の抑制: Windows API(`FindWindow`等)でプロジェクトのウィンドウを操作する必要がある場合、必ず `DoEvents` を挟み、UIスレッドのスタックをクリアすること。
3. Set To Nothing: VBAのガベージコレクションは頼りにならない。大規模なコレクション処理の終了時には、参照している全オブジェクトを `Nothing` に戻すのが、安定したシステムを構築するエンジニアの矜持だ。
—
4. システム間連携における「UniqueID」の正当性
外部システム(ExcelやSQL Serverなど)とデータを同期させる場合、「UniqueID」をマッピングキーとして外部DBに保存せよ。
もし外部システムでタスクの順序が入れ替わったとしても、VBA側で `Tasks.UniqueID(外部DBの値)` を呼び出せば、物理的な行位置に関わらず、確実に正しいタスクを操作できる。これこそが、プロジェクト管理における「Single Source of Truth(単一の真実)」の原則である。
—
5. 最後に:アーキテクトからの助言
「IDが変わったからリンクが切れた」という報告は、開発者の敗北を意味する。
Project VBAは、Excel VBAのような「セル操作」の延長にあるのではない。オブジェクト指向の深い理解と、永続的識別子の重要性を理解した者だけが扱える「高精度な機械」である。
君たちが記述するコードは、プロジェクトの命運を左右する。タスクのID一つに、エンジニアとしての魂を込めろ。
—
次回の講義では、MS Projectの「カスタムフィールド」を使用した依存関係のメタデータ管理と、バイナリ転送によるパフォーマンスの極致について解説する。
