こんにちは!マクロの記録のその先へ進み、いよいよ「Project VBA」の世界に足を踏み入れたのですね。素晴らしい挑戦です。
Excel VBAとは一味違うMicrosoft Projectのオブジェクトモデルに戸惑っていませんか?「タスクの並び順を変えたい」「WBSの階層をきれいに整えたい」——そんな現場の悩みを一発で解決するのが、今回解説する`OutlineLevel`(アウトラインレベル)プロパティです。
ここをクリアすれば、Project VBAの基本はバッチリですよ。さあ、手作業の地獄から抜け出すための第一歩を、私と一緒に踏み出しましょう!
—
なぜ「アウトラインレベル」の制御が重要なのか?
プロジェクト管理において、WBS(Work Breakdown Structure)の階層構造は命です。例えば、以下のようなフラット(階層のない)なタスクリストがあったとします。
- 企画フェーズ
- 要件定義
- 基本設計
- 開発フェーズ
- コーディング
- 単体テスト
これらを一つずつインデントボタンでポチポチ階層化していく……。タスクが100個あったら気が遠くなりますよね。しかも、後から仕様変更でタスクが追加されたらやり直しです。
これをVBAで一瞬にして自動構築できたらどうでしょう?
Project VBAでは、タスクの`OutlineLevel`というプロパティを書き換えるだけで、タスクの親子関係(WBS)を自在にコントロールできるのです。
—
押さえておきたい基本:OutlineLevelの仕組み
Projectのタスクには、それぞれ「何番目の階層にいるか」を示す数値が割り振られています。
- レベル 1:大親(プロジェクトの大きなフェーズなど。例:「企画フェーズ」)
- レベル 2:子(具体的な作業のグループ。例:「要件定義」)
- レベル 3:孫(さらにブレイクダウンした作業)
ここで初心者が一番最初にハマる「絶対的な罠」をお伝えしておきます。
> 【重要】インデント(レベル変更)は、上から順番に行う必要がある!
> Projectは、「親がいないのに子だけをレベル2にする」ような不自然なデータ構造を許しません。VBAで階層を操作するときは、必ず「親を作ってから、その下の子のレベルを下げる」という順番を守る必要があります。
—
実践!フラットなリストからWBSを自動構築するVBAコード
それでは、実務でそのまま使える基本のコードを見ていきましょう。
今回は、あらかじめ名前だけが並んだフラットなタスクに対し、コード内で「どのタスクが何階層目か」を指定してWBSを構築するサンプルです。
Sub CreateWBSHierarchy()
‘ —————————————————————-
‘ 概要: フラットなタスクリストに対してOutlineLevelを設定し、
‘ WBSの階層構造(親子関係)を動的に構築する基本マクロ
‘ —————————————————————-
Dim t As Task
‘ エラーハンドリングの基本:プロジェクトが開かれていない場合などをガード
If ActiveProject.Tasks.Count = 0 Then
MsgBox “タスクが登録されていません。”, vbExclamation, “エラー”
Exit Sub
End If
‘ 画面描画を停止してマクロの実行速度を爆上げする(Project VBAの基本テク!)
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
ニ
‘ 【ステップ1】まず全タスクのレベルを「1」にリセット(フラット化)
For Each t In ActiveProject.Tasks
If Not t Is Nothing Then
t.OutlineLevel = 1
End If
Next t
‘ 【ステップ2】タスクのID(または行番号)を指定して階層を構築する
‘ ※ここでは分かりやすくIDを指定してレベルを変更しています
‘ 実際の現場では、Excelや別データからループで読み込ませると強力です。
‘ 例:ID 2 と 3 を、ID 1(親)の子(レベル2)にする
‘ ※IDを指定するときは ActiveProject.Tasks(ID) または .UniqueID(ID) を使います
‘ (注意)ProjectのタスクIDは1から始まります
If ActiveProject.Tasks.Count >= 3 Then
ActiveProject.Tasks(1).OutlineLevel = 1 ‘ 大親
ActiveProject.Tasks(2).OutlineLevel = 2 ‘ 子
ActiveProject.Tasks(3).OutlineLevel = 2 ‘ 子
End If
If ActiveProject.Tasks.Count >= 6 Then
ActiveProject.Tasks(4).OutlineLevel = 1 ‘ 大親
ActiveProject.Tasks(5).OutlineLevel = 2 ‘ 子
ActiveProject.Tasks(6).OutlineLevel = 3 ‘ 孫(子の中の子)
End If
Application.ScreenUpdating = True
MsgBox “WBSの階層化が完了しました!”, vbInformation, “成功”
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub
コードのここがポイント!
1. `Application.ScreenUpdating = False`
大量のタスクを操作するとき、画面が毎回チラつくと処理がものすごく遅くなります。VBAの実行前には画面更新を止め、終わったら`True`に戻す。これがプロの技です。
2. `Not t Is Nothing` という判定
Projectの `Tasks` コレクションを `For Each` で回すとき、削除されたタスクの跡地などが「Nothing」として取得されることがあります。これをそのまま操作すると「オブジェクト変数が見つかりません」というエラーになるため、このガード文は呪文のように必ずセットで覚えましょう。
—
初心者が必ずハマる「罠」と回避策
罠1:レベルを飛ばしていきなり「3」にしようとしてエラーになる
前述した通り、レベル2の親がいない状態で、あるタスクの `OutlineLevel = 3` に設定すると、Projectは怒り出します。
必ず 「1 ➔ 2 ➔ 3」という階段を一段ずつ降りるように レベルを設定してください。
罠2:IDとUniqueIDの混同
コード内で `ActiveProject.Tasks(2)` と書いた場合、これは「現在画面の上から2番目にあるタスク(ID: 2)」を指します。
しかし、タスクを並び替えたり削除したりすると、この「ID」は変わってしまいます。実務でマスターデータ等と連携させる場合は、不変のIDである `UniqueID` をキーにしてタスクを特定するアプローチが重要になってきますが、まずは今回の「上からの順番(ID)」を使った基本形をマスターすれば十分です。
—
おわりに
お疲れ様でした!今回はタスクの階層構造を操る `OutlineLevel` の基本を解説しました。
「たったこれだけのプロパティ操作で、あの面倒なWBSのインデント作業が自動化できるのか!」と実感いただけたのではないでしょうか。
ここをクリアできれば、次は「ExcelのCSVからWBSを一撃で生成するマクロ」や「条件に応じて自動で色や太字を変える処理」など、応用編への扉が開きます。
あなたのProject VBAの旅は、まだ始まったばかりです。分からないことがあれば、いつでもまたこのブログに帰ってきてくださいね。応援しています!
