Project VBAの深淵へ:祝日一括更新で学ぶ「リソースカレンダー」の極意
こんにちは。現場で「なぜかプロジェクトが回らない」という悩みを解消し続けてきたチーフアーキテクトです。
多くのエンジニアが「マクロの記録」から一歩踏み出したとき、最初にぶつかる壁が「MS Projectのオブジェクト構造」です。特にリソースの稼働管理は、一歩間違えると計画全体が崩壊する繊細な領域。
今回は、毎年恒例の「祝日メンテナンス」を題材に、リソースの「カレンダー例外」を操作する本質的な技術を伝授します。これさえ理解すれば、Project VBAの設計思想の半分は掌握したも同然です。
—
1. なぜ「カレンダー例外」なのか?
MS Projectにおいて、リソースは「カレンダー」という時間軸の支配下にあります。タスクに割り当てられたリソースが「働ける日・働けない日」を管理するのが例外(Exceptions)です。
自動化のキモは、「全リソースに対して、同じ例外をどう適用するか」という一括処理のアルゴリズムにあります。
私たちが目指す処理フロー
1. 外部データ(Excel等)から祝日リストを読み込む
2. プロジェクト内の全リソースを取得する
3. 各リソースのカレンダーに対して「例外」を追加する
—
2. 極限のコード:祝日一括適用プロシージャ
このコードは、単に動くだけではありません。エラーハンドリングと、Project特有のオブジェクト参照の作法を凝縮しています。
Sub UpdateResourceHolidays()
Dim proj As Project
Dim res As Resource
Dim cal As Calendar
Dim holidayDate As Date
Dim holidayName As String
‘ プロジェクトオブジェクトの明示的な取得
Set proj = ActiveProject
‘ ここではデモとして固定値ですが、実務ではExcelからループで読み込んでください
holidayDate = #1/1/2025#
holidayName = “元日”
On Error GoTo ErrorHandler
‘ 全リソースをループする
For Each res In proj.Resources
‘ リソースが割り当てられているベースカレンダーを取得
Set cal = res.Calendar
‘ 例外を追加(重複エラーを避けるため、事前に存在確認をすべきだが、
‘ Projectの例外オブジェクトはユニーク制約があるためエラーを拾うのが定石)
cal.Exceptions.Add Type:=pjDayTypeWorking, _
Start:=holidayDate, _
Finish:=holidayDate, _
Name:=holidayName
Debug.Print “更新完了: ” & res.Name & ” – ” & holidayName
Next res
MsgBox “全リソースの祝日更新が完了しました。”, vbInformation
Exit Sub
ErrorHandler:
‘ 既に登録済みなどのエラーは無視して続行する設計が現場では重要
If Err.Number = 1101 Then Resume Next
MsgBox “エラー発生: ” & Err.Description
End Sub
—
3. 初学者が陥る「3つの罠」
このコードを書くとき、多くの人がつまずくポイントがあります。ここを突破すれば、あなたはもう中級者です。
① 「Set」を忘れるな
VBAでは、オブジェクト(ResourceやCalendarなど)を扱う際に `Set` が必須です。これを忘れると「オブジェクト変数またはWithブロック変数が設定されていません」というエラーが頻出します。Project VBAはオブジェクトの海です。`Set` は「ポインタを指し示す儀式」だと考えてください。
② 例外の重複(1101エラー)
既に同じ日付が登録されている場合、Projectは怒ります(エラーコード1101)。上記のコードでは `Resume Next` で回避していますが、現場では「登録済みならスキップする」というロジックを `If` 文で組むのがよりスマートです。
③ 稼働率(稼働日)の定義
`pjDayTypeWorking` と `pjDayTypeNonWorking` の違いを意識してください。今回は「休日」なので `pjDayTypeNonWorking` を指定するのが正解ですが、あえて `Working` を指定して「休日出勤」を管理することも可能です。
—
4. 現場のアーキテクトからのアドバイス
「マクロの記録」で生成されるコードは、操作をそのままトレースするだけの「あらすじ」に過ぎません。しかし、今回のような一括処理を書くことは、「Projectの裏側で何が起きているか」という構造理解に直結します。
- リソースを増やすとき: 全リソースをループするのではなく、特定のグループやフィルタリングされたリソースに限定する設計を検討してください。
- パフォーマンス: 数千行のタスクや数百のリソースがある場合、`Application.ScreenUpdating = False` を活用して描画を止めるのが、プロの技です。
—
最後に:自動化の先にあるもの
祝日の手動更新に追われる時間は、本来「プロジェクトの進捗分析」や「リスクの芽を摘む」ために使うべき貴重なリソースです。
「面倒な作業はコードに任せ、人間はより高度な判断に集中する」。これが業務自動化の真髄です。このコードをベースに、皆さんの現場に合わせてカスタマイズしてみてください。
何か不明点があれば、またいつでも聞いてください。Project VBAの深淵で、いつでも待っていますよ。
