こんにちは!プロジェクト管理の現場で、日々数々のスケジュールと格闘お疲れ様です。
「一つのファイルだけなら手作業でリンクを貼れるけれど、別ファイルにある親プロジェクトのタスクと、子プロジェクトのタスクを自動で結びつけたい……」
そんな壁にぶつかったことはありませんか?
マクロの記録から一歩抜け出し、いよいよProject VBAの深淵に足を踏み入れたあなたへ。今回は、実務で絶対に直面する「プロジェクト横断の依存関係(クロスプロジェクトリンク)をVBAで完全に自動化する手法」を、優しく、そして本質的な知見を交えてお伝えします。
ここをクリアすれば、あなたのProject VBAのスキルは間違いなく一皮むけますよ。一緒にバッチリマスターしていきましょう!
—
1. なぜ「別ファイルのタスク」とのリンクは難しいのか?
MS Projectでは、同じファイル内であれば `Task.Predecessors.Add` のようなメソッド一発でタスク間の依存関係(先行・後続)を作ることができます。
しかし、これが「別ファイル(外部プロジェクト)」になると話が変わります。
- 相手のファイルが閉じていたらリンクを張れない(開く必要がある)。
- タスク名で指定しても、途中で名前が変わったらリンクが切れる(ユニークなIDで特定すべき)。
- Project特有の「外部タスク(External Task)」の挙動を理解していないと、メモリ上でエラーを起こす。
こうした泥臭い問題を、VBAのコードでスマートに解決していきましょう。
—
2. 全体像:自動化のステップ
今回のプログラムが行う処理の流れは以下の通りです。
1. 外部プロジェクトファイルを開く(すでに開いていなければ読み込み専用で開く)。
2. 自ファイル(アクティブプロジェクト)のタスクから、リンク先を探す(カスタムフィールドなどに「外部タスク名」や「ID」が記載されていると仮定)。
3. 外部プロジェクトのタスクオブジェクトを取得する。
4. 先行タスクとしてリンクを追加する。
—
3. 実装コード:クロスプロジェクトリンク自動生成マクロ
実務でそのままコピペして、少し書き換えるだけで使える実践的なコードを用意しました。VBAエディタ(Alt + F11)を開き、標準モジュールに貼り付けてみてください。
Sub CreateCrossProjectLink()
Dim prjCurrent As Project
Dim prjExternal As Project
Dim tskCurrent As Task
Dim tskExternal As Task
‘ — 設定エリア —
Const EXT_FILE_PATH As String = “C:\Projects\MasterSchedule.mpp” ‘ リンク先(外部)のファイルパス
Const EXT_TASK_ID As Long = 5 ‘ 外部プロジェクト側のタスクID
Const TARGET_CURRENT_ID As Long = 3 ‘ 自ファイルのタスクID
‘ ——————
Set prjCurrent = ActiveProject
On Error GoTo ErrorHandler
‘ 1. 外部プロジェクトがすでに開いているか確認し、なければ開く
Set prjExternal = GetOrOpenProject(EXT_FILE_PATH)
If prjExternal Is Nothing Then
MsgBox “外部プロジェクトを開けませんでした。”, vbCritical
Exit Sub
End If
‘ 2. 自ファイルのタスクを取得
Set tskCurrent = prjCurrent.Tasks.Item(TARGET_CURRENT_ID)
‘ 3. 外部ファイルのタスクを取得
Set tskExternal = prjExternal.Tasks.Item(EXT_TASK_ID)
‘ 4. クロスプロジェクトリンクの作成(先行タスクとして追加)
‘ ※ExternalProjectのタスクをPredecessorsに指定することで自動的に外部リンクが生成されます
tskCurrent.Predecessors.Add Predecessor:=tskExternal
MsgBox “外部プロジェクトとのリンクが正常に完了しました!”, vbInformation, “自動化成功”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
‘ If Not prjExternal Is Nothing Then prjExternal.Close False ‘ 必要に応じて閉じる処理
End Sub
‘ — 補助関数:プロジェクトが開いていなければ開き、開いていればオブジェクトを返す —
Function GetOrOpenProject(filePath As String) As Project
Dim p As Project
Dim fileName As String
‘ パスからファイル名だけを抽出
fileName = Mid(filePath, InStrRev(filePath, “\”) + 1)
‘ 既に開いているかチェック
For Each p In Application.Projects
If p.Name = fileName Then
Set GetOrOpenProject = p
Exit Function
End If
Next p
‘ 開いていない場合はファイルを開く(バックグラウンドで読み込み専用)
On Error Resume Next
Application.FileOpenEx Name:=filePath, ReadOnly:=True
If Err.Number = 0 Then
Set GetOrOpenProject = ActiveProject
Else
Set GetOrOpenProject = Nothing
End If
On Error GoTo 0
End Function
—
4. コードの深掘り解説:ここがポイント!
① `GetOrOpenProject` 関数の知恵
外部ファイルを参照する際、毎回 `FileOpenEx` を実行すると、すでに開いている場合に「二重オープン」の警告が出たり、処理が重くなったりします。
この補助関数では、「すでに開いているプロジェクトのコレクション(`Application.Projects`)を総当たりでチェックし、開いていなければ新しく開く」という安全な設計にしています。これがプロの技です。
② 外部タスクの指定
`tskCurrent.Predecessors.Add Predecessor:=tskExternal`
ここが本質です。MS ProjectのVBAでは、異なるプロジェクトのタスクオブジェクト同士であっても、直接 `Predecessors.Add` の引数に渡すだけで、自動的に「外部先行タスク([外部] タスク名…)」としてのリンクを構築してくれます。
—
5. 陥りやすい罠とエラー回避のコツ
現場でこのコードを動かすとき、初心者が必ずハマる「落とし穴」が2つあります。
1. ファイルパスの書き間違い・ファイルが存在しない
- → `FileOpenEx` が失敗すると `ActiveProject` が意図しないものを指してしまうことがあります。必ずエラーハンドリング(`On Error`)を挟みましょう。
2. 外部タスクのID(ID番号)が変わってしまう
- → 今回はシンプルな解説のために `ID`(行番号的なもの)を指定していますが、タスクが挿入・削除されるとIDはズレます。本番運用では、タスクの `UniqueID`(ユニークID:変更されない固有番号) を使って検索するロジックに拡張するのがベストプラクティスです。
—
まとめ
今回は「プロジェクト横断の依存関係をVBAで自動リンクする手法」について解説しました。
- 外部ファイルを安全に開いてオブジェクトをキャッチする。
- `Predecessors.Add` に別プロジェクトのタスクを渡すだけでリンクできる。
この2つさえ押さえておけば、複雑なマルチプロジェクト管理もボタン一つで同期できるようになります。手作業のコピペ地獄から抜け出し、より本質的なプロジェクトマネジメントに時間を使えるようになりますよ。
ここをクリアしたあなたなら、もうProject VBAの初級者は卒業です!ぜひご自身の環境で試してみてくださいね。
