【入門編】WBSコードの不整合を自動修復:階層インデントとWBS番号の同期エラーを解消する – Project VBA解析バイブル

スポンサーリンク

こんにちは!プロジェクト管理の現場で、ExcelやMS Projectを行ったり来たりしながら奮闘していませんか?

「マクロの記録」から一歩抜け出して、いざ本格的なProject VBAを書こうとしたとき、多くの人が最初に直面するのが「タスクの階層構造(WBS)とインデントのズレ問題」です。

手動でタスクを追加したり削除したりしているうちに、WBS番号がバラバラになり、インデントの階層と番号が完全に迷子になる……。プロジェクトマネージャーなら誰もが一度は頭を抱えるこの悪夢を、VBAの力で一刀両断してみましょう。

ここをクリアすれば、Project VBAの基本とオブジェクト操作の本質はバッチリです。一緒に優しく、深く、マスターしていきましょう!

1. なぜWBSの整合性は崩れるのか?(現場の落とし穴)

MS Projectは非常に優秀なツールですが、ユーザーが自由にタスクを挿入・移動・インデント(レベル上げ・下げ)できるがゆえに、以下のような「ねじれ現象」が起きやすくなります。

  • 親タスクを消したのに、子タスクのインデントがそのまま残った
  • WBS番号(OutlineNumber)を手入力または古いアドインで振ったまま放置した
  • タスクの並び順(ID順)と、実際の階層構造がちぐはぐになっている

人間がこれを目視で修正しようとすると、大規模なプロジェクトであればあるほど発狂しそうになります。だからこそ、「タスクのインデントレベルを正として、WBS番号と表示を自動で再計算・同期するスクリプト」を常備しておく必要があるのです。

2. Project VBAの基本:タスク階層を操る3つの武器

コードを書く前に、Project VBA特有の「お作法」を押さえておきましょう。Excel VBAとは少し空気感が違います。

1. `ActiveProject.Tasks` コレクション
プロジェクト内のすべてのタスクが詰まった箱です。ただし、ここにアクセスするときは「空っぽのタスク(Nothing)」が混ざる可能性があるため、ループ処理では注意が必要です。
2. `OutlineLevel` プロパティ
タスクが「何階層目にあるか」を示します(一番上がレベル1)。
3. `OutlineNumber` プロパティ
「1」「1.1」「1.1.2」といった、お馴染みのWBSのアウトライン番号です。

3. 【実践】WBS自動修復・同期スクリプト

それでは、開発現場でそのままコピペして使える実用コードを公開します。
このスクリプトは、現在のタスクの「インデントレベル(OutlineLevel)」をスキャンし、それに伴う正しいWBS番号の体系を再構築するロジックを持っています。

Sub RepairAndSyncWBS()
‘ =====================================================================
‘ 処理概要: タスクのインデントレベルを基準に、WBSの整合性を自動修復する
‘ 対象読者: マクロの記録を卒業し、現場の自動化に挑むエンジニアへ
‘ =====================================================================

Dim tsk As Task
Dim levelCounters(1 To 10) As Integer ‘ 最大10階層までのカウンター配列
Dim currentLevel As Integer
Dim i As Integer

‘ エラーハンドリングの基本:画面描画を止めて爆速化&チラつき防止
Application.ScreenUpdating = False

On Error GoTo ErrorHandler

‘ 1. カウンター配列の初期化
For i = 1 To 10
levelCounters(i) = 0
Next i

‘ 2. プロジェクト内の全タスクを上から順に走査
For Each tsk In ActiveProject.Tasks
‘ 削除されたタスク(Nothing)やサマリーの不整合を防ぐガード
If Not tsk Is Nothing Then

‘ サマリータスクや通常タスクの現在階層を取得
currentLevel = tsk.OutlineLevel

‘ 階層に応じた番号の採番ロジック
levelCounters(currentLevel) = levelCounters(currentLevel) + 1

‘ 深い階層のカウンターをリセット(例: レベル2が変わったらレベル3以下をリセット)
For i = currentLevel + 1 To 10
levelCounters(i) = 0
Next i

‘ 【重要】MS Project標準のOutlineNumberは読み取り専用の場合があるため、
‘ ここではカスタムテキストフィールド(Text1など)に正しいWBS体系を焼き付けるか、
‘ あるいは標準のアウトライン再計算を促すトリガーとして活用します。
‘ 実務では、Text1に独自の綺麗フォーマットを格納することが多いです。

Dim generatedWBS As String
generatedWBS = levelCounters(1)

For i = 2 To currentLevel
If levelCounters(i) > 0 Then
generatedWBS = generatedWBS & “.” & levelCounters(i)
End If
Next i
Cat
‘ デバッグウィンドウに出力(動作確認用)
Debug.Print “ID: ” & tsk.ID & ” | Name: ” & tsk.Name & ” | Level: ” & currentLevel & ” | WBS: ” & generatedWBS

‘ 例として、カスタムフィールド「Text1」に整合性の取れたWBSを書き込む
tsk.Text1 = generatedWBS

End If
Next tsk

Application.ScreenUpdating = True
MsgBox “WBSの整合性修復が完了しました!”, vbInformation, “成功”
Exit Sub

ErrorHandler:
Application.ScreenUpdating = True
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “異常終了”
End Sub

4. コードの深掘り解説:ここがエンジニアの腕の見せ所

初心者から一歩抜け出すために、上記のコードで使われている「プロの技」を2つ解説します。

① 配列を使った階層カウンター(`levelCounters(1 To 10)`)

WBS番号を自動生成するとき、一番難しいのは「親が変わったときに子以下の番号をどうリセットするか」です。
ここでは配列を使い、`currentLevel`(現在の階層)が来たらその番号をインクリメントし、それより深い階層(`currentLevel + 1` 以降)のカウンターを強制的に `0` にリセットしています。このアルゴリズムを知っているだけで、ツリー構造を扱うVBAのスキルが跳ね上がります。

② 画面描画の停止(`Application.ScreenUpdating = False`)

タスクが数千行ある巨大なプロジェクトファイルを操作するとき、VBAが1行動くたびに画面を再描画していると、処理が終わるまでにコーヒーを何杯も飲むことになります。
「処理の最初に止め、終わったら戻す」。これはパフォーマンスチューニングの基本中の基本です。

5. 陥りやすいエラーと回避の呪文

Project VBAを書いていると、必ずと言っていいほど以下のエラーにぶつかります。

  • エラー:「オブジェクト変数が設定されていません。(Error 91)」
  • 原因: `For Each tsk In ActiveProject.Tasks` の中で、途中の行が削除されて空っぽ(Nothing)になっているタスクに触ろうとしたときにおきます。
  • 対策: サンプルコードのように `If Not tsk Is Nothing Then` というガード節を必ず挟みましょう。

まとめ:自動化の快感を味わおう

今回は、WBSのインデントと番号の整合性を自動修復するスクリプトを通じて、Project VBAのオブジェクト操作の基本と、ツリー構造を扱うアルゴリズムを解説しました。

手作業で数時間かかっていたWBSの整理が、ボタン一つ(あるいはイベントトリガー)で一瞬で終わる――この瞬間こそが、プログラミングを学ぶ最大の醍醐味です。

ここをクリアしたあなたなら、もう「マクロの記録」に頼る必要はありません。ぜひ自分のプロジェクト環境にこのコードを組み込み、スマートな自動化ライフを満喫してくださいね!

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