【入門編】マイルストーンタスクを自動抽出し、先行タスクとのリンクを自動化するマクロ – Project VBA解析バイブル

スポンサーリンク

こんにちは!Project VBAの世界へようこそ。
マクロの記録ボタンを押すだけのステージから抜け出し、「自分の手でプロジェクトを意のままにコントロールしたい」と願うあなたへ。今日は、実務で最高に役立つ「マイルストーンの自動抽出と依存関係の構築」というテーマを授けましょう。

ここをクリアすれば、Project VBAの基本構造、そしてタスク(Task)オブジェクトのライフサイクルを操る面白さがグッと見えてきます。難しい理論は抜きにして、優しく、そして本質的なところまで一緒に駆け抜けていきましょう!

なぜ、マイルストーンとリンクの自動化が必要なのか?

プロジェクトが大規模になればなるほど、数千行にも及ぶWBS(Work Breakdown Structure)の管理に悲鳴を上げることになります。
「〇〇完了」「キックオフ」といった重要な節目(マイルストーン:期間がゼロのタスク)を手動で探し出し、一つひとつ直前のタスクとリンク(先行タスクの設定)を張っていく……。想像しただけで気が遠くなりませんか? 人間の手作業は必ずミスを生みます。

これをVBAの力で一瞬にして自動化できたらどうでしょう?
あなたがやるべきことは、タスク名に特定のキーワード(例:「【完了】」など)を含めるだけ。あとはマクロが賢く見つけ出し、直前のタスクとの間に「終了-開始(FS)」の依存関係を美しく結んでくれます。

まず押さえておきたい!Project VBAの基本思想

Excel VBAと違い、MS ProjectのVBAには独特の「重み」と「作法」があります。ここを知らないと、「なぜか動かない」「エラーが消えない」という泥沼にハマります。

1. ActiveProjectがすべての中心
今、画面で開いているプロジェクトファイルを操作するのが `ActiveProject` です。
2. タスクの集合体は `Tasks` コレクション
プロジェクト内の全タスクは `ActiveProject.Tasks` という箱(コレクション)に入っています。
3. リンクは `TaskPredecessors` または `LinkTasks` で結ぶ
タスク同士を繋ぐときは、「どのタスクの先行として追加するか」を指定します。

実装コード:マイルストーン自動化の全貌

それでは、開発の現場でそのままコピペして使える実践的なコードを公開します。VBAエディタ(Alt + F11)を開き、標準モジュールに貼り付けてみてください。

Sub AutoDetectMilestonesAndLink()
‘ =====================================================================
‘ テーマ: 特定キーワードを含むタスクをマイルストーン化し、直前タスクとリンクする
‘ 執筆者: チーフアーキテクトからのエール
‘ =====================================================================

Dim tsk As Task
Dim prevTsk As Task
Dim keyword As String

‘ 検索するキーワード(タスク名に含まれていたらマイルストーンにする)
keyword = “【完了】”

‘ 念のため、処理の高速化と画面描画のロック(MS Projectでは非常に重要です)
Application.Cursor = jConst.pjWait
On Error GoTo ErrorHandler

Set prevTsk = Nothing

‘ プロジェクト内のすべてのタスクを上から順に走査する(ループ処理)
For Each tsk In ActiveProject.Tasks
‘ タスクが「Nothing(空)」でないか、かつサマリータスク(親タスク)ではないかをチェック
If Not tsk Is Nothing Then
If Not tsk.Summary Then

‘ タスク名にキーワードが含まれているか判定
If InStr(tsk.Name, keyword) > 0 Then

‘ 1. マイルストーン化(期間を 0 日にする)
tsk.Duration = “0d”

‘ 2. 直前の通常タスクが存在する場合、依存関係(FSリンク)を構築する
If Not prevTsk Is Nothing Then
‘ 既存のリンク重複エラーを防ぐため、安全に先行タスクを追加
‘ 引数: 先行タスク, リンク形式(pjLinkFinishToStart)
tsk.TaskPredecessors.Add Predecessor:=prevTsk, Type:=pjLinkFinishToStart
End If

End If

‘ 次のループのために「直前のタスク」を現在のタスクに更新
‘ (※マイルストーンであっても、次のタスクの基準とするため保持します)
Set prevTsk = tsk

End If
End If
Next tsk

‘ 終了処理
Application.Cursor = jConst.pjDefault
MsgBox “マイルストーンの抽出とリンクの自動構築が完了しました!”, vbInformation, “成功”
Exit Sub

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

ジックリとコードを眺めてみてください。「なぜここで `Summary` をチェックしているのか?」気付きましたか?
MS Projectでは、親タスク(子を持つまとめのタスク)の期間や進捗は、自動的に子タスクから計算されます。親タスクに対して無理やり `Duration = “0d”` なんて設定してしまうと、プロジェクト全体のスケジュール計算エンジンが混乱を起こしてしまいます。
「実作業を行う末端のタスク(Leaf Task)だけを対象にする」というプロの視点が、ここに活きています。

初学者がハマりやすい「3大トラップ」と回避策

Project VBAを書き始めると、誰もが一度は次のような壁にぶつかります。先回りして回避策を伝授しましょう。

1. `For Each tsk In ActiveProject.Tasks` で「Nothing」エラーが出る

  • 原因: MS Projectのタスク番号(ID)は途中で削除されると欠番が生じ、`Tasks` コレクションの中に「実体のない空っぽ(Nothing)」の要素が生まれることがあります。
  • 対策: コード内でも行っているように、必ず `If Not tsk Is Nothing Then` で存在確認を行ってください。これを怠ると「オブジェクト変数が設定されていません」というエラーの餌食になります。

2. リンクが二重に張られてエラーになる

  • 原因: すでに先行タスクが設定されている状態のタスクに対して、同じリンクをプログラムから何度も追加しようとすると、Projectが「そんなことできません!」と怒り出します。
  • 対策: 実務でより堅牢なマクロにする場合は、リンクを追加する前に `tsk.Predecessors` の数を確認する、あるいは一度既存のリンクをクリアするなどのガード節を入れると完璧です。

3. 画面のちらつきと動作の重さ

  • 原因: タスク数が数百、数千と増えてくると、VBAが1行実行するたびに画面のガントチャートが再描画され、処理がカメのように遅くなります。
  • 対策: 今回のコードの冒頭に入れた `Application.Cursor = jConst.pjWait` のように、システムに負荷をかけない配慮がプロの証です。さらに大規模な処理では画面更新を一時停止するテクニックも有効ですよ。

さあ、次のステップへ踏み出そう!

「マクロの記録」という安全なゆりかごから飛び出し、自分で変数を定義し、条件分岐やオブジェクトのコレクションを操る――。この感覚が掴めれば、あなたの業務効率化の可能性は無限大に広がります。

「ここをクリアすれば、Project VBAの基本はバッチリですよ」。
今日のコードをあなたのプロジェクトファイルに組み込んで、ボタン一発でガントチャートが整う瞬間をぜひ体感してください。感動すること間違いなしです。

それでは、次のアーキテクチャでお会いしましょう。ハッピー・コーディング!

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