こんにちは!Project VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自分の手でプロジェクトを意のままにコントロールしたい――そう思っているあなたへ。
今回は、業務で非常に役立つ「開いているプロジェクトの全タスクをコピーし、クリーンな新規プロジェクトファイルとして保存する雛形生成術」を解説します。
「複雑になりすぎたスケジュールから、特定のタスクだけを抜き出して別ファイルにしたい」
「定型的なプロジェクトのテンプレートをVBAで一瞬にして作りたい」
そんな現場のニーズに直結するテクニックです。ここをクリアすれば、Project VBAの基本構造やオブジェクトの扱い方がグッと身につきますよ。さあ、一緒に扉を開けていきましょう!
—
1. なぜ「タスクのコピー」がVBA初心者にとって最高の教材なのか?
MS ProjectのVBA(Project VBA)は、Excel VBAとよく似ていますが、「タスク」「リソース」「ビュー」「プロジェクト」という独特な階層構造(オブジェクトモデル)を持っています。
特に「別ファイルへのコピー&新規保存」という一連の流れには、Project VBAを使いこなすためのエッセンスがすべて詰まっています。
- アクティブなプロジェクトの特定 (`ActiveProject`)
- 新規プロジェクトの作成 (`FileNew`)
- タスクの複製とプロパティの継承 (`OutlineIndent` やループ処理)
- 安全なファイル保存 (`FileSaveAs`)
これらを一つずつ紐解いていけば、あなたも脱・初心者です!
—
2. 全体像:今回作成するVBAコード
まずは、開発の現場でそのままコピペして動かせる完成形のコードをお見せします。
VBE(Visual Basic Editor)を開き、標準モジュールに貼り付けて実行してみてください。
Sub GenerateTemplateProject()
Dim srcProject As Project
Dim newProject As Project
Dim t As Task
‘ 1. エラーハンドリングの準備
On Error GoTo ErrorHandler
‘ 2. コピー元(現在アクティブなプロジェクト)を定義
‘ ※何もプロジェクトが開いていない場合のガード処理
If Application.Projects.Count = 0 Then
MsgBox “コピー元のプロジェクトが開かれていません。”, vbCritical, “エラー”
Exit Sub
End If
Set srcProject = ActiveProject
‘ 3. 新規プロジェクトファイルを作成
‘ FileNewメソッドを実行すると、新しいプロジェクトがアクティブになります
FileNew
Set newProject = ActiveProject
‘ 4. コピー元の全タスクを新規プロジェクトへ複製する
‘ ※Project VBAでは、タスクを単純にコピー&ペーストするより、
‘ 名前や期間をループで移す方がクリーンで確実です。
Dim targetTask As Task
For Each t In srcProject.Tasks
‘ サマリー行や空行(Nothing)を除外する安全策
If Not t Is Nothing Then
If t.Summary = False Then ‘ 通常タスクの場合
Set targetTask = newProject.Tasks.Add(t.Name)
targetTask.Duration = t.Duration
targetTask.Start = t.Start
targetTask.Finish = t.Finish
‘ 必要に応じて他のプロパティ(コストやメモなど)もここに追加可能
Else
‘ サマリータスク(親タスク)の場合の処理
Set targetTask = newProject.Tasks.Add(t.Name)
‘ ※インデント構造の再現は階層の深さに応じた処理が必要ですが、
‘ 今回は「全てのタスクをフラットに、あるいは名前を引き継ぐ」基本形としています。
End If
End If
Next t
‘ 5. 新規プロジェクトを保存する
‘ ダイアログを出さずに特定パスに保存する場合は FileSaveAs を使います
‘ 今回は安全のために、デスクトップに「Template_Project.mpp」として保存します
Dim savePath As String
savePath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\Template_Project.mpp”
‘ すでに同名ファイルがある場合の予期せぬ上書きを防ぐ簡易チェック
If Dir(savePath) <> “” Then
If MsgBox(“同名のファイルが既に存在します。上書きしますか?”, vbYesNo + vbQuestion, “確認”) = vbNo Then
MsgBox “保存を中止しました(タスクの生成は完了しています)。”, vbInformation, “完了”
Exit Sub
End If
Kill savePath ‘ 既存ファイルを削除
End If
newProject.FileSaveAs Name:=savePath, Format:=”MS Project.mpp”
MsgBox “新規テンプレートの生成が完了しました!” & vbCrLf & “保存先: ” & savePath, vbInformation, “成功”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & “エラー番号: ” & Err.Number & vbCrLf & Err.Description, vbCritical, “エラー”
End Sub
—
3. コードの急所を噛み砕く!重要ポイント解説
先輩エンジニアとして、このコードの「絶対に押さえておくべき本質」を3つに絞って解説します。
① `ActiveProject` という「今を見つめる目」
ProjectのVBAでは、複数のプロジェクトファイルを同時に開くことができます。そのため、「今、どのファイルを操作しているのか?」を明示することが極めて重要です。
`Set srcProject = ActiveProject` と最初に変数へ格納することで、「操作している最中にユーザーが別のプロジェクトをクリックしてアクティブが変わってしまった!」というバグ(事故)を防いでいます。
② タスクの「丸ごとコピー」より「再生成」が安全な理由
Excelのように「シート全体をコピーする」ような機能が、Projectのタスクには単純な1行の命令としては存在しません(※BaselineやWBSの制約があるため)。
そのため、上記のコードではコピー元のタスクを `For Each` で1つずつ読み込み、新規プロジェクト側 (`newProject.Tasks.Add`) で再構築しています。
これによって、不要なリンク切れや、前プロジェクト固有のUUID(識別子)の競合を防ぎ、「まっさらで美しいクリーンな雛形」を生成できるのです。
③ パスの動的取得 (`WScript.Shell`)
コード内の `savePath` の部分で、Windowsのデスクトップパスを自動取得する技を使っています。
硬直した絶対パス(例: `C:\Users\Yamada\Desktop\…`)を書いてしまうと、他のメンバーのPCで実行した時に必ず「ファイルが見つかりませんエラー」になります。環境に依存しないパスの書き方は、プロのエンジニアの必須作法です。
—
4. 初学者がハマりやすい「3大トラップ」と回避策
Project VBAを書き始めると、多くの人が次のような壁にぶつかります。あらかじめ知っておけば怖くありません!
1. 「タスクが何もありません」エラー(`Nothing` の罠)
- 原因: Projectの `Tasks` コレクションには、削除されたタスクの欠番や、空の行が含まれていることがあります。
- 対策: コード内でも入れている `If Not t Is Nothing Then` というガード節を必ず挟みましょう。これを忘れると「オブジェクト変数または With ブロック変数が見つかりません」という呪いのエラーが出ます。
2. 保存ダイアログが勝手に出て固まる
- 原因: `FileSaveAs` を引数なしで実行すると、ExcelやProjectの標準保存ダイアログがポップアップし、マクロがユーザーの操作を待ち続けて止まってしまいます。
- 対策: `Name:=savePath` のように引数を明示し、サイレント(自動)で保存を完結させましょう。
3. プロジェクトが開いていない状態で実行した
- 原因: 何もプロジェクトがない状態で `ActiveProject` を呼ぶと即座にエラーになります。
- 対策: `If Application.Projects.Count = 0 Then` で、事前に開かれているプロジェクトがあるかを検知する優しさをコードに持たせましょう。
—
5. おわりに:ここからあなたの自動化の旅が始まる
お疲れ様でした!今回は「開いているプロジェクトのタスクを別ファイルへコピーして新規作成する」という、実務直結の雛形生成術を解説しました。
このコードをベースに、
- 「特定のキーワード(例: ‘【必須】’)が含まれるタスクだけを抽出する」
- 「進捗率(%完了)をリセットして0%にする」
といった条件分岐(`If`文)を1枚噛ませるだけで、あなたの業務を何時間も短縮する最強のオリジナルツールへと進化します。
「ここをこう改造したいんだけど、どう書けばいい?」といった疑問があれば、いつでもエンジニア仲間として相談に乗りますよ。
基礎をマスターしたあなたなら、もう大丈夫。自信を持って、次の自動化へ挑んでください!
