Project VBAの深淵:WBS階層構造を「コードとして」操るための極限設計
現場のプロジェクトリーダー諸君。君たちが日々苦しんでいるのは、MS ProjectのGUIをポチポチとクリックしてタスクの階層を構築する、あの不毛な作業ではないか?
「WBSを別のプロジェクトにコピーしたい」という要件に対し、標準機能のインポート・エクスポートに頼り切っているようでは、現場の自動化エンジニアとしては三流だ。プロジェクトの構造(WBS)は、データであると同時に「ロジック」そのものだ。これをCSVやJSONという「可搬性のある形式」で掌握できなければ、大規模な工数管理や多拠点連携は夢物語に終わる。
今日は、Project VBAを使い倒し、WBSの階層構造をJSON/CSVとして自在に変換するための「堅牢な設計論」を叩き込む。
—
1. なぜ「フラットなデータ」から「階層」を復元する設計が必要なのか
Projectのタスクは`OutlineLevel`(アウトラインレベル)という属性を持っている。しかし、このプロパティを単純に上から順に書き出すだけでは、インポート時に親子の紐付けが崩壊するリスクがある。
避けるべきアンチパターン:
- タスク名だけで階層を管理しようとすること(重複名の排除が必要になる)
- インポート時に`Task.OutlineIndent`を乱発すること(パフォーマンスが極端に低下する)
目指すべき設計指針:
1. 階層構造の正規化: インポート時は「階層レベル」を属性として持たせたフラットなリストとして扱い、再帰的に処理する。
2. 依存関係の分離: 前提条件(Predecessors)はタスク名ではなく「一意のID(UID)」で管理する。
3. トランザクション管理: 全タスクを読み込んでから一括適用するのではなく、`Application.Calculation = pjManual`で計算を止め、メモリ上で構築してから解放する。
—
2. 実装コード:JSON/CSV変換のコア・ロジック
以下は、Projectのタスク構造をフラットなJSON形式(あるいはCSVの行)に変換し、それを復元するためのエンジニアリングの要だ。
‘ ———————————————————
‘ 階層構造のエクスポート:タスク情報をJSON風オブジェクトへ
‘ ———————————————————
Public Sub ExportWBS()
Dim tsk As Task
Dim jsonOutput As String
‘ プロジェクト内の全タスクを走査
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
‘ パフォーマンスを考慮し、最低限の属性のみ抽出
‘ UID, Name, OutlineLevel, Predecessors
jsonOutput = jsonOutput & “{“”UID””:” & tsk.UniqueID & _
“,””Name””:””” & tsk.Name & “””” & _
“,””Level””:” & tsk.OutlineLevel & “},” & vbCrLf
End If
Next tsk
‘ ここでファイル出力処理(FileSystemObjectを使用)
Debug.Print jsonOutput
End Sub
‘ ———————————————————
‘ 階層構造のインポート:WBSを再現する際の手順
‘ ———————————————————
Public Sub ImportWBS(taskData As Collection)
Dim app As MSProject.Application
Set app = Application
‘ 計算をオフにして高速化
app.Calculation = pjManual
‘ インポートロジック:
‘ 1. タスクを作成(Task.Add)
‘ 2. OutlineIndentで階層を調整
‘ 3. 最後に依存関係(Predecessors)をUID経由で再構築
app.Calculation = pjAutomatic
End Sub
—
3. 現場で「バグらせない」ための3つの鉄則
① UIDの保持とマッピング
CSV/JSONにエクスポートする際、MS Projectが自動生成する`ID`(行番号)をキーにしてはいけない。行の挿入でIDは変わるからだ。必ず`UniqueID`を使用せよ。 外部ファイル上ではこのUIDを外部キーとして依存関係を記述し、インポート時に「旧UID→新UID」のマッピングテーブルをメモリ上に生成する設計が不可欠だ。
② パフォーマンスの重みを知る
`Task.OutlineIndent`をループ内で実行すると、その都度Projectは再計算を行う。数千行規模のWBSを扱う場合、`Application.Calculation = pjManual` を忘れることは死を意味する。処理終了後に必ず `CalculateAll` を呼び出すのがプロの作法だ。
③ エラーハンドリングの極致
インポート失敗時のロールバックは容易ではない。インポート処理を開始する前に、必ず `ActiveProject.ProjectSummaryTask` を起点としたバックアップ(あるいは別ファイルへのコピー)を取るか、`On Error GoTo` で強制的に計算モードを自動に戻す安全装置を仕込め。
—
結論:自動化は「構造」への理解から始まる
WBSを外部ファイル化するということは、君たちが管理しているのは単なるスケジュールではなく「ビジネスの論理構造」だということだ。
このコンバーターを実装し、現場に展開すれば、これまで手作業で行っていた「定型的なプロジェクトの立ち上げ」が数秒で終わるようになる。だが、ツールを作るだけで満足するな。「なぜその階層なのか」「なぜその依存関係なのか」というプロジェクトの本質をコードに落とし込める者だけが、真の自動化エンジニアと名乗れる。
さあ、エディタを開け。君のプロジェクトを、コードで支配する時間だ。
