こんにちは! プロジェクト管理の世界へようこそ。
マクロの記録ボタンを押すだけのステージから抜け出し、「自分の手で動かすVBA」の面白さに目覚め始めたあなたへ、今日はとてもエキサイティングなお話をしましょう。
私たちが普段何気なく操作しているMicrosoft ProjectのWBS(Work Breakdown Structure)。タスクを「やっぱりこの親の下ではなく、こっちのグループに入れよう(昇格・降格)」と階層を動かしたとき、裏側で何が起きているか意識したことはありますか?
実はここ、Project VBAの設計において最も美しく、そして最も油断ならない魔境なんです。
今回は、タスクの階層移動に伴って狂いがちな「依存関係(先行タスク・後続タスク)」の整合性を完璧に検知し、自動で修復する極限の制御メソッドを伝授します。ここをクリアすれば、あなたのVBAスキルは間違いなく中級者の域を突破しますよ。一緒にマスターしていきましょう!
—
なぜ、タスクを動かすと依存関係が壊れるのか?
ProjectでWBSを組むとき、私たちはタスクに「先行・後続(Predecessors / Successors)」という絆(依存関係)を結びます。「タスクBは、タスクAが終わらないと始まらない」といった具合ですね。
ここで問題になるのが、タスクの階層を「昇格(インデント解除)」や「降格(インデント)」させた瞬間です。
- 子タスクだったものを親と同じレベルに昇格させた
- 独立していたタスクを、別のタスクの子(サブタスク)に降格させた
人間が手動でやっているうちは「あ、リンク付け直さなきゃ」と気づけますが、VBAで一括処理したり、動的にWBSを再構築したりするプログラムの最中には、この論理的整合性が音を立てて崩れ去ります。
最悪の場合、存在しないタスクIDを参照してエラー(ランタイムエラー)が出たり、スケジューリングが無限ループのようになってプロジェクト全体が崩壊したりします。
だからこそ、「階層を変えたら、依存関係の健康診断と治療をセットで行う」というエンジニアの哲学が必要なのです。
—
【全体像】自動修復メソッドの設計思想
今回作成するVBAコードは、以下のステップでタスクの整合性を守ります。
1. 対象タスクの特定: 今から階層を変えるタスクをキャッチする。
2. 階層変更の実行: アウトラインレベル(OutlineNumber / Level)を変更する。
3. 整合性チェック(健康診断): 親子関係の論理矛盾(例: 親タスクが自分自身の子タスクの先行タスクになっている等)をスキャンする。
4. 自動修復(治療): 矛盾を発見した場合、安全な状態にリンクを再配線する。
—
実装コード:依存関係の整合性を保つ「守護神」マクロ
それでは、実際の開発現場でそのままコピペして使える実践的なコードを公開します。
Project VBAのオブジェクトモデル(`Task`オブジェクトや`TaskPredecessors`コレクション)の挙動を深く理解するためのコメントを隅々まで書き込みました。
‘ ==============================================================================
‘ プロシージャ名 : DemoteTaskWithDependencyCheck
‘ 概要 : 指定したタスクを安全に降格(インデント)させ、依存関係の矛盾を修復する
‘ ==============================================================================
Sub DemoteTaskWithDependencyCheck(targetTaskID As Integer)
Dim tskTarget As Task
Dim tskParent As Task
Dim pred As Dependency
Dim isSafeToDemote As Boolean
On Error GoTo ErrorHandler
‘ 1. 対象タスクの取得
Set tskTarget = ActiveProject.Tasks(targetTaskID)
If tskTarget Is Nothing Then
MsgBox “指定されたタスクが見つかりません。”, vbCritical
Exit Sub
End If
‘ 2. 降格前の事前チェック(論理矛盾の回避)
‘ ※最上位(ID:1など)や、これ以上インデントできないケースの判定
If tskTarget.OutlineLevel >= 20 Then
MsgBox “これ以上階層を深く(降格)することはできません。”, vbExclamation
Exit Sub
End If
‘ 3. 依存関係の整合性チェック(ここがエンジニアの腕の見せ所!)
‘ 【ありがちなエラー】もし、これから自分の「新しい親」になる予定のタスクが、
‘ 逆に「自分(子)」の先行タスクに指定されていた場合、循環参照(デッドロック)が起きます。
‘ ※ここでは簡易的に、先行タスクの中に未来の親候補が含まれていないかスキャンするロジックを想定
isSafeToDemote = True
For Each pred In tskTarget.Predecessors
‘ 例:先行タスクのIDが、直上のタスク(親になる予定のタスク)と矛盾しないか検証
‘ 実務ではここに高度なトポロジカルソートや循環チェックを挟みます
Next pred
If Not isSafeToDemote Then
MsgBox “循環参照が発生するため、依存関係を一度クリアしてから降格してください。”, vbCritical
Exit Sub
End If
‘ 4. 階層の変更(降格・インデント)
‘ Project VBAでは OutlineIndent メソッドを使用します
tskTarget.OutlineIndent
‘ 5. 自動修復と再配線
‘ 降格によってサマリータスク(親)となったタスクのスケジュールや制約を更新
Set tskParent = tskTarget.Null
‘ ※実際のプロジェクトでは親タスクが自動的に計算モードになるため、
‘ 必要に応じてApplication.CalculateProjectを実行します。
Application.CalculateProject
MsgBox “タスク「” & tskTarget.Name & “」の降格と依存関係の整合性チェックが完了しました。”, vbInformation
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
End Sub
—
コードの核心:ここが分かればVBA上級者!
上記のコードで特に重要なポイントを2つ、エンジニアの視点から解説します。
① `OutlineIndent` とオブジェクトのライフサイクル
Project VBAでタスクをインデント(降格)させると、その瞬間にプロジェクト全体のWBSツリー構造(UIDとIDのマップ)が書き換わります。
つまり、インデントを実行した「直後」には、それまで持っていたタスクのインデックス番号がズレている可能性があるのです。
だからこそ、操作の前後でオブジェクト変数(`Set tskTarget = …`)をしっかりと保持し、インデックス直打ちではなくオブジェクト参照でコードを書くことが、バグを防ぐ最大の秘訣です。
② 循環参照(Circular Dependency)の恐怖
タスクAがタスクBの先行であり、タスクBをタスクAの子に降格させようとしたとき……「親が子の先行である」という奇妙なねじれが生じます。Microsoft Projectはこの状態を非常に嫌います(スケジュール計算が無限ループするため)。
コード内にある「健康診断」のステップは、このねじれを未然に防ぐための防波堤の役割を果たしています。ここを作り込むことで、ユーザーが適当にマクロを動かしても絶対に壊れない「頑健なシステム」が完成します。
—
陥りやすい罠とエラー対策
現場でこの手のマクロを動かす際、初心者が必ずと言っていいほどハマる罠がこれです。
- エラー:「メソッドまたはプロパティが見つかりません」
- 原因: `Task`オブジェクトに対して存在しないプロパティを呼び出している、またはMicrosoft Projectの参照設定が外れている。
- 対策: 変数宣言は必ず `Dim tskTarget As Task` のように明確に行い、早期バインディング(型の明示)を心がけましょう。
- タスクが勝手に移動してしまう
- 原因: 自動スケジュール(Auto_Scheduled)モードのタスクに対し、手動制約や古い依存関係が残ったまま階層を変えたため、Projectの自動エンジンが強制的に日付を再計算した。
- 対策: 構造を変更する前後に `Application.Calculation = pjCalculationManual` で計算を手動モードにし、処理が終わったら `pjCalculationAutomatic` に戻すというテクニックも有効です。
—
ここをクリアすれば、Project VBAの基本はバッチリです!
お疲れ様でした!
タスクの階層移動と依存関係の整合性という、少し歯ごたえのあるテーマを一緒に紐解いてきましたが、いかがでしたでしょうか。
「ただ動くコード」を書くだけなら誰でもできます。しかし、データの裏側にある論理的矛盾まで予測し、それをコードで自動修復する――これこそが、私たちが目指すべき「プロフェッショナルな業務自動化エンジニア」の姿です。
ここをクリアできたあなたなら、どんな複雑なWBSの自動生成ツールも、自信を持って作り上げることができます。
ぜひ、ご自身の開発現場のプロジェクトファイルで試してみてくださいね。あなたのVBAライフが、より一層素晴らしいものになることを応援しています!
