【入門編】Project VBAにおける「タスクID」と「ユニークID」の使い分けと罠 – Project VBA解析バイブル

スポンサーリンク

こんにちは!Project VBAの世界へようこそ。
マクロの記録から一歩踏み出し、「さあ、本格的にWBSの自動化や進捗管理システムを作るぞ!」と意気込んでコードを書き始めたものの……なぜかタスクの依存関係がめちゃくちゃになったり、思わぬエラーに頭を抱えたりしていませんか?

大丈夫。ここをクリアすれば、あなたもProject VBAの本質を捉えた立派な自動化エンジニアです。

今回は、現場で誰もが一度はハマる「タスクID」と「ユニークID」の深い罠と、それを華麗に回避して強靭な依存関係を構築するプロの技術を、優しく、そして徹底的に解説していきますね。

1. なぜ、タスクの依存関係が勝手に狂うのか?

MS Projectを操作していて、こんな現象に直面したことはありませんか?
「タスクAの先行タスクにタスクBを指定したはずなのに、タスクを並び替えたり削除したりしたら、なぜか全く関係ないタスクが紐づいている……!」

これは、初心者のあなたがミスをしたわけではありません。MS Projectが持っている「2つの顔(ID)」の仕様を知らないことが原因です。

「タスクID (ID)」と「ユニークID (UniqueID)」の決定的な違い

MS ProjectのVBAを触る上で、この違いを理解することは、爆弾の赤と青のコードどちらを切るべきか知るくらい重要です。

  • タスクID (`ID` プロパティ)
  • 特徴: ガントチャートの左端に表示される「通し番号(1, 2, 3……)」です。
  • 性格: 非常に気まぐれです。ユーザーがタスクを上下に並び替えたり、途中のタスクを削除したりすると、番号は自動的に振り直されます
  • VBAでの扱い: 人間が見るには分かりやすいですが、プログラムの「アンカー(基準)」として使うのは絶対にご法度です。
  • ユニークID (`UniqueID` プロパティ)
  • 特徴: タスクが作成された瞬間に割り振られる、固有の識別番号です。
  • 性格: 不変の絶対王者です。タスクをどこに移動しようが、途中のタスクをごっそり削除しようが、一度振られたUniqueIDは絶対に変わりません
  • VBAでの扱い: 自動化スクリプトでタスクを確実に追跡・制御するための必須パスポートです。

> 先輩からのアドバイス:
> 「VBAでタスクを操作するとき、`ActiveProject.Tasks(1)` のような『タスクID』ベースの指定は、動的な処理(並び替えや削除が伴うもの)では秒で破綻します。常に `UniqueID` を基準にオブジェクトを捉える癖をつけましょう。」

2. 【図解風】タスクIDとユニークIDの運命の分かれ道

イメージしてみましょう。以下のようなWBSがあるとします。

[初期状態]
ID: 1 | UniqueID: 101 | タスク名: 要件定義
ID: 2 | UniqueID: 102 | タスク名: 基本設計
ID: 3 | UniqueID: 103 | タスク名: 詳細設計

ここで、ユーザーがうっかり「ID: 1(要件定義)」を削除しました。するとMS Projectはこう変化します。

[「要件定義」削除後]
ID: 1 | UniqueID: 102 | タスク名: 基本設計 ← 元ID:2が「1」に繰り上がった!
ID: 2 | UniqueID: 103 | タスク名: 詳細設計 ← 元ID:3が「2」に繰り上がった!

もし、あなたの書いたVBAコードが「ID 1 と ID 2 の間に依存関係を張る」というロジックだったらどうなるでしょう?
本来やりたかったのは「基本設計 と 詳細設計」の紐付けだったはずが、削除によってIDがズレたせいで、全く意図しないタスク同士が結ばれてしまいます。これが「タスクIDの罠」です。

3. 実践!UniqueIDを使って堅牢な依存関係を自動設定する

では、この罠を完全に回避し、タスクがどう並び替えられようとも意図した依存関係(先行・後続関係)を確実に結ぶVBAコードを書いてみましょう。

以下のコードは、「特定のユニークIDを持つタスクを探し出し、安全に前提条件(先行タスク)を定義する」実用的なプロシージャです。

Sub CreateSafeDependency()
Dim tskPredecessor As Task
Dim tskSuccessor As Task
Dim targetPredecessorUID As Long
Dim targetSuccessorUID As Long

On Error GoTo ErrorHandler

‘ 【設定】紐付けたいタスクの「ユニークID」をあらかじめ定義しておく
‘ ※タスクID(1, 2, 3…)ではなく、UniqueID(不変の値)を指定するのがポイント!
targetPredecessorUID = 101 ‘ 先行タスクのユニークID
targetSuccessorUID = 102 ‘ 後続タスクのユニークID

‘ — 1. ユニークIDを元に、タスクオブジェクトを確実に取得する —
Set tskPredecessor = GetTaskByUniqueID(targetPredecessorUID)
Set tskSuccessor = GetTaskByUniqueID(targetSuccessorUID)

‘ タスクが見つかったかどうかの厳密なチェック
If tskPredecessor Is Nothing Then
MsgBox “先行タスク (UniqueID: ” & targetPredecessorUID & “) が見つかりません。”, vbCritical
Exit Sub
End If

If tskSuccessor Is Nothing Then
MsgBox “後続タスク (UniqueID: ” & targetSuccessorUID & “) が見つかりません。”, vbCritical
Exit Sub
End If

‘ — 2. 依存関係(先行タスク)を設定する —
‘ Task.Predecessors.Add メソッドを使用します
‘ 引数には先行タスクを指定します。ここでもUniqueIDベースで取得したオブジェクトなので安全です。
tskSuccessor.Predecessors.Add Task:=tskPredecessor

MsgBox “タスク「” & tskSuccessor.Name & “」の先行タスクに「” & tskPredecessor.Name & “」を正常に設定しました!”, vbInformation
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
End Sub

‘ =================================================================
‘ 【ヘルパー関数】UniqueIDからTaskオブジェクトを安全に逆引きする
‘ =================================================================
Function GetTaskByUniqueID(ByVal uniqueID As Long) As Task
Dim tsk As Task

‘ Project内の全タスクをループしてUniqueIDが一致するものを探す
‘ (※数千件レベルの巨大プロジェクトでない限り、このスキャンで十分高速です)
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
If tsk.UniqueID = uniqueID Then
Set GetTaskByUniqueID = tsk
Exit Function
End If
End If
Next tsk

‘ 見つからなかった場合は Nothing が返る
Set GetTaskByUniqueID = Nothing
End Function

コードの解説とエンジニアのこだわりポイント

1. ヘルパー関数 `GetTaskByUniqueID` の導入
MS Projectの標準オブジェクトモデルには「`ActiveProject.Tasks.UniqueID(101)` のような一発で取得するメソッド」が用意されていないことが多いです。そのため、全タスクを走査して安全にオブジェクトを釣り上げる「ヘルパー関数」を用意するのがプロの常道です。
2. `Not tsk Is Nothing` の防御的プログラミング
MS Projectの `Tasks` コレクションは、途中のタスクが削除されると「空のスロット(Nothing)」が発生することがあります。これをそのまま `tsk.UniqueID` で評価すると、容赦なく「オブジェクト変数が設定されていません」エラー(実行時エラー 91)が飛んできます。ループ内での `Is Nothing` チェックは必須の作法です。
3. `Predecessors.Add` によるクリーンな依存関係構築
タスクIDに依存しないオブジェクト参照(`tskPredecessor`)を渡しているため、このコードを実行する前にユーザーがタスクの並び替えを行っていようが、行っていなかろうが、狙ったタスク同士が確実に一本の鎖で結ばれます。

まとめ:ここをクリアすれば、Project VBAの基本はバッチリ!

いかがでしたでしょうか?
「タスクID」と「ユニークID」の仕様の違い、そしてなぜUniqueIDをベースに設計しなければならないのか、その理由が心とコードのレイヤーで腑に落ちたはずです。

  • 「見た目の番号(ID)」は気まぐれだから信用しない。
  • 「固有の番号(UniqueID)」をアンカーにしてロジックを組み立てる。
  • エラーを防ぐために `Is Nothing` のガードを忘れない。

この3つをマスターすれば、あなたの作るWBS自動化マクロは、現場のどんな無茶なタスク操作に対してもビクともしない、頑健でプロフェッショナルなシステムへと生まれ変わります。

さあ、自信を持って次のコードを書きに行きましょう。あなたのVBAライフが、よりエキサイティングで快適なものになりますように!

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