こんにちは!Project VBAの世界へようこそ。チーフアーキテクトの私です。
マクロの記録ボタンを押して生成されたコードを眺めて、「よし、動いた!」と喜んでいた時期はもう卒業です。実際に実務のWBS(Work Breakdown Structure)をVBAで自動制御しようとした瞬間、あなたはおそらくこんな怪奇現象に直面したはずです。
「あれ? タスクを1行消したら、次のタスクのリンク(前提条件)がめちゃくちゃになったぞ……?」
そう、これこそが多くの開発者が涙を飲む、MS Projectの「ID」と「UniqueID」の罠です。
今回は、タスクの挿入や削除にビクともしない、「UniqueIDをキーにした堅牢なリンク設定術」をマスターしましょう。ここをクリアすれば、あなたのVBAスキルは確実に中級者の領域へとステップアップします。温かく丁寧に解説していきますので、ぜひ最後までついてきてくださいね!
—
1. なぜ「ID」ではなく「UniqueID」なのか?(基本の理解)
まずは、MS Projectが持つ2種類の「番号」の正体を暴いておきましょう。ここが本質的な分水嶺です。
- ID(通し番号):
画面の一番左に表示される「1, 2, 3…」という番号です。タスクを上へ移動させたり、途中で行を削除したりすると、番号はダイナミックに振り直されます。
- UniqueID(固有ID):
タスクが生成された瞬間にProjectが内部で割り振る、絶対に変わらない不変のIDです。行を削除しようが、一番上に移動させようが、この番号は一生モノとしてタスクに張り付きます。
マクロの記録が教えてくれない恐怖
もしあなたが「ID=1のタスクの後に、ID=2のタスクをリンクする」というコードを書いていたら、それは時限爆弾を仕込んでいるようなものです。ユーザーが途中で1行タスクを挿入した瞬間、IDのズレによって全く関係ないタスク同士がリンクされてしまいます。
だからこそ、VBAで堅牢なWBSを構築したいなら、「操作は常にUniqueIDをキーにして行う」というのが鉄則なのです。
—
2. 【実践】UniqueIDでタスクを確実に捉えてリンクする
百聞は一見に如かず。実際に「先行タスクのUniqueID」を指定して、後続タスクとの間にリンク( predecessors )を張る安全なVBAコードを見てみましょう。
開発の現場でそのままコピペして使えるように、たっぷりコメントを入れています。
Sub CreateRobustTaskLink()
Dim prj As Project
Set prj = ActiveProject
Dim tskPredecessor As Task
Dim tskSuccessor As Task
‘ 【重要】IDではなく、UniqueIDでタスクオブジェクトを取得します
‘ ここでは例として「UniqueIDが 10 のタスク」から「UniqueIDが 11 のタスク」へリンクを張ります
Dim targetPredecessorUID As Long
Dim targetSuccessorUID As Long
targetPredecessorUID = 10
targetSuccessorUID = 11
On Error GoTo ErrorHandler
‘ TaskList.UniqueIDItem メソッドを使って、確実に対象のタスクを捕まえます
Set tskPredecessor = prj.Tasks.UniqueIDItem(targetPredecessorUID)
Set tskSuccessor = prj.Tasks.UniqueIDItem(targetSuccessorUID)
‘ 既に同じリンクが存在する場合のエラーを防ぐため、一度クリアするなどの配慮も実務では有効です
‘ リンクの設定(Predecessorsプロパティに先行タスクのUniqueIDを渡すのが最も安全)
‘ ※ Project VBAでは、UniqueIDを文字列やコロン区切りで指定してリンクを制御できます
‘ プレデセッサ(先行タスク)のUniqueIDを指定してリンクを追加
tskSuccessor.Predecessors = tskPredecessor.UniqueID & “FS” ‘ FS = 終了-開始 (Finish-Start)
MsgBox “UniqueID: ” & targetPredecessorUID & ” から ” & _
targetSuccessorUID & ” へのリンク設定が完了しました!”, vbInformation
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: 指定したUniqueIDのタスクが存在しないか、不正な値です。”, vbCritical
End Sub
コードのここがポイント!
- `prj.Tasks.UniqueIDItem(UID)`:これが今回の主役です。画面上のIDではなく、不変のUniqueIDからピンポイントでTaskオブジェクトを引き当てます。
- `tskSuccessor.Predecessors = …`:リンク文字列にUniqueIDを使うことで、万が一タスクの並び順がシャッフルされても、Projectが自動的に正しい相手を探してリンクを維持してくれます。
—
3. 陥りがちなエラーと回避のテクニック
現場でこのロジックを組み込む際、初心者がハマりやすい「落とし穴」が2つあります。ここを知っておくだけで、デバッグの時間が何時間も浮きますよ。
エラー①:UniqueIDが存在しない(削除済み)
ユーザーが手動でタスクを削除した場合、指定したUniqueIDはProjectの歴史から消え去ります。存在しないUniqueIDに対して `UniqueIDItem` を呼び出すと、「実行時エラー 1100: 指定された項目が見つかりません。」が発生します。
【対策】
必ずループを回す前や処理の直前に、そのUniqueIDを持つタスクが本当に存在するかチェックする、あるいは上記のコードのように `On Error` でトラップする防御的プログラミングを徹底しましょう。
エラー②:文字列型と数値型の型ミスマッチ
VBAでは `Long` 型と `String` 型の暗黙の型変換が行われますが、リンク文字列(`Predecessors`)に値を代入する際は、明示的に `&` で文字列結合を行うか、`CStr()` 関数を使って型を明確にしておく方が、予期せぬバグを防げます。
—
4. まとめ:プロフェッショナルなVBAエンジニアへの第一歩
今回は、Project VBAにおけるタスクの「UniqueID」と「ID」の不一致を解消し、削除や挿入に強いリンク設定術を解説しました。
- 画面上の「ID」は流動的。信用してはいけない。
- 内部の「UniqueID」は不変。リンクや検索のキーは必ずこれを使う。
- `Tasks.UniqueIDItem()` を使ってオブジェクトを確実につかみ取る。
ここをクリアできれば、あなたの作るWBS自動化ツールは、現場のプロジェクトマネージャーから「おっ、このマクロ、全然壊れないな!」と絶賛されるクオリティに達します。
基本をしっかり押さえたあなたなら、もう大丈夫。自信を持って次の自動化へ挑戦してくださいね。応援しています!
