【入門編】Taskオブジェクトの「名前」と「ID」と「UniqueID」を使い分ける:実務で事故を防ぐための命名規則と参照術 – Project VBA解析バイブル

スポンサーリンク

こんにちは!Project VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、「自分の手で動かすプログラム」を書こうとしているあなたを、私は心から歓迎します。

Excel VBAの経験がある方なら、「VBAなんて余裕だろ」と思われるかもしれません。しかし、Microsoft Project(MSP)のオブジェクトモデルは、Excelのペラペラな「シートとセル」の概念とは全く違います。タスクは追加され、削除され、ガントチャート上でグリグリと並び替えられます。

この「動的な世界」でタスクを正確に掴まないと、「あぁ!昨日まで動いていたマクロが、タスクの順番を変えた途端に全然関係ないタスクを書き換えてしまった……!」という、背筋が凍るような現場の事故(バグ)を引き起こします。

今回は、そんな事故を未然に防ぐためのパスポート、「Name」「ID」「UniqueID」の完全使い分け術を伝授します。ここをクリアすれば、あなたも立派なProject VBAのアーキテクトの仲間入りです。一緒に本質をマスターしていきましょう!

1. 3つの識別子(Name・ID・UniqueID)の正体を見抜け

まずは、タスクを指し示す3つの看板の性格をしっかりと理解しましょう。

[ タスクのオブジェクト ]
├─ Name : 「設計書作成」 (人間が見る名前。重複あり・変更自由)
├─ ID : 3 (その場の表示順。並び替えで変わる流動的な番号)
└─ UniqueID : 105 (MS Projectが裏で振る永久不滅の背番号)

① Name(名前)

  • 特徴: 人間が読むための文字列(例: `”要件定義”`, `”コーディング”`)。
  • 危険性: 世界に一つとは限りません。 同じ名前のタスクが複数存在することが日常茶飯事です。したがって、プログラムで「このタスクを特定して処理する」ためのキーとしては絶対に信用してはいけません。

② ID(ID)

  • 特徴: ガントチャート上で上から何番目かを示す番号(1, 2, 3…)。
  • 危険性: ユーザーがタスクの順番をドラッグ&ドロップで入れ替えたり、途中のタスクを削除したりすると、ガタガタと変化します。
  • 例:「タスクID: 3」の行を削除すると、それまでID: 4だったタスクが繰り上がって「ID: 3」になります。
  • 用途: 画面上の表示用、またはマクロの実行中に「上から順にループ処理する」といった一時的な用途にのみ使います。

③ UniqueID(ユニークID)

  • 特徴: タスクが作成された瞬間にMS Projectが自動採番し、そのタスクが消去されるまで絶対に変わらない永久不滅の背番号です。
  • 安全性: 並び替えを行おうが、途中の行が削除されようが、この番号は微動だにしません。
  • 用途: データベースや外部ファイルと連携する時、あるいは「特定のタスクを確実につかまえて処理したい」時の最強の識別子です。

2. 事故が起きる現場:なぜ「ID」や「Name」では失敗するのか?

初心者がやりがちな、最も恐ろしいコードを見てみましょう。

Sub DangerousCode()
‘ IDが2のタスクの期間を10日に変更しよう!
ActiveProject.Tasks(2).Duration = 480 ‘ 480分 = 1日 (※MSPの内部単位は分)

MsgBox “処理が完了しました!”
End Sub

一見、何の問題もないように見えますよね。「上から2番目のタスクの期間を変更する」という意味ですから。

しかし、もしこのマクロを実行する直前に、現場の担当者がうっかり「1番目のタスク」を削除してしまったらどうなるでしょう?
元々3番目にあったタスクが繰り上がって「ID: 2」になっています。その結果、あなたが意図していない全く別のタスクの期間が書き換わってしまうのです。これが実務で大問題になる「静的コードの罠」です。

3. 実務で絶対的な安全を生む「UniqueID参照術」

では、プロのエンジニアはどう書くのか。
答えは簡単です。「UniqueID」を使ってタスクを指名買いするのです。

UniqueIDを使ってタスクオブジェクトを取得する構文

Projectオブジェクトからタスクを引く際、`Tasks`コレクションに渡すインデックスは、実はデフォルトでは「ID」ではなく「UniqueID」として機能します(※厳密には `Tasks(ID)` と `Tasks.UniqueID(UniqueID)` の挙動の違いに注意が必要ですが、確実なのは後者のメソッド、あるいはループによる探索です)。

より安全で確実な、タスクの「UniqueID」を検索して操作する実用コードを見てみましょう。

Sub SafeTaskUpdate()
Dim tsk As Task
Dim targetUniqueID As Long

‘ 操作したいタスクのUniqueIDが「105」だと分かっているとする
targetUniqueID = 105

‘ エラーハンドリングの準備
On Error GoTo ErrorHandler

‘ UniqueIDを指定してタスクをダイレクトに掴みに行く(安全な方法)
Set tsk = ActiveProject.Tasks.UniqueID(targetUniqueID)

‘ プロパティを書き換える
tsk.Name = “【完了】詳細設計”
tsk.Duration = 960 ‘ 2日間 (480分 × 2)

MsgBox “UniqueID: ” & targetUniqueID & ” のタスクを安全に更新しました!”, vbInformation
Exit Sub

ErrorHandler:
MsgBox “指定されたUniqueIDのタスクは既に削除されているか、存在しません。”, vbCritical
End Sub

このコードの優れたポイント

1. 行の入れ替えに強い: ガントチャートのどこにタスクが移動していようと、`Tasks.UniqueID(105)` は一発でそのタスクを特定します。
2. 存在チェックができる: もしそのタスクがすでに削除されていた場合、エラー(Run-time error ‘1100’: このようなインデックスを持つアイテムはありません)が発生しますが、`On Error`でスマートに捕捉し、プログラムの暴走を防げます。

4. 全タスクを安全に走査(ループ)するベストプラクティス

「ファイル内のすべてのタスクをチェックして、条件に合うものを加工したい」というケースは多々あります。この時も、先ほどの原則が生きてきます。

Sub LoopAllTasksSafely()
Dim tsk As Task

‘ ActiveProject.Tasks を回すときは For Each が鉄則
For Each tsk In ActiveProject.Tasks
‘ tsk が Nothing(空っぽ)でないことを確認する防御的コード
If Not tsk Is Nothing Then

‘ 例:もしタスク名に「レビュー」が含まれていたら、優先度を「最高」にする
If InStr(tsk.Name, “レビュー”) > 0 Then
tsk.Priority = pjPriorityHighest

‘ デバッグウィンドウに出力 (IDとUniqueIDの両方を記録しておく)
Debug.Print “更新完了 -> ID: ” & tsk.ID & ” / UniqueID: ” & tsk.UniqueID & ” / 名称: ” & tsk.Name
End If

End If
Next tsk

MsgBox “すべてのタスクの走査が完了しました。”, vbInformation
End Sub

ここがエンジニアの知見!

  • `For Each tsk In ActiveProject.Tasks` を使うことで、IDのズレを気にする必要がなくなります。
  • Project VBAでは、削除されたタスクのメモリ領域が特殊な状態で残ることがあるため、`If Not tsk Is Nothing Then` というヌルチェック(生存確認)を入れるのが、プログラマとしての作法(マナー)であり、クラッシュを防ぐ盾となります。

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

いかがでしたでしょうか? 今回のポイントをギュッと凝縮して振り返ります。

1. Name は人間が見るもの。重複や変更があるため、キーにしてはいけない。
2. ID は「上からの順番」。並び替えや削除で変動するため、静的なハードコーディングは事故の元。
3. UniqueID は永久不滅の背番号。実務で特定のタスクを操作・連携する時は、必ずこれを使う。

この3つの違いを意識するだけで、あなたが書くマクロの信頼性は劇的に跳ね上がり、「現場で壊れない、美しい自動化ツール」へと生まれ変わります。

ここをクリアしたあなたなら、もうマクロの記録の卒業生ではありません立派なProject VBAのエンジニアです。ぜひ実際のプロジェクトファイルで試してみてくださいね。それでは、次のステップでお会いしましょう!

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