【テクニカル・上級編】Projectの「カレンダー」設定をVBAで操作する:稼働日・休日設定の自動反映ツール – Project VBA解析バイブル

スポンサーリンク

現場の「工数ズレ」を根絶せよ:Project VBAによるカレンダー自動同期の極致

Projectのスケジュール管理において、最も忌むべきは「稼働日定義の不整合」だ。Excelで管理された祝日や社休日と、ProjectのBaseCalendarが乖離している。この些細なズレが、積み重なれば数週間の工数バグを招く。

本稿では、Excelをマスターデータとし、Projectのオブジェクトモデルを直接叩いてカレンダーを同期させる、堅牢かつ高速なアーキテクチャを提示する。単なる自動化ではない。「Projectの内部エンジンを制御下に置く」ための技術論だ。

1. オブジェクトライフサイクルの管理と「静的な堅牢性」

VBAにおける最大の敵はメモリリークではない。不適切なオブジェクト参照による「予期せぬインスタンスの増殖」だ。Projectの`Application`オブジェクトは重い。むやみなSetは避け、スコープを最小化せよ。

特に`BaseCalendar`を操作する際、コレクション内のインデックスに依存してはならない。名前による一意な特定こそが、長期保守における唯一の正解だ。

2. 実装:BaseCalendar同期エンジン

以下のコードは、Excel上の祝日リストをProjectへ流し込むためのコアロジックである。`Application.BaseCalendars`に対する直接的な書き込みは、パフォーマンスを最大化するために、`ScreenUpdating`をオフにするだけでなく、操作対象以外のオブジェクト参照を徹底的に排除している。

‘ 必要な参照設定: Microsoft Project 16.0 Object Library
Option Explicit

Public Sub SyncExcelToProjectCalendar()
Dim projApp As Object ‘ Late Bindingで環境依存を排除
Dim pj As Project
Dim cal As Calendar
Dim ws As Worksheet
Dim lastRow As Long, i As Long

‘ メモリ管理の鉄則: 画面更新の停止と警告抑制
Application.ScreenUpdating = False

On Error Resume Next
Set projApp = GetObject(, “MSProject.Application”)
If projApp Is Nothing Then
MsgBox “Projectが起動していません。”
Exit Sub
End If
On Error GoTo 0

Set pj = projApp.ActiveProject
Set ws = ThisWorkbook.Sheets(“HolidayList”)
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

‘ 対象カレンダーの取得(存在しない場合は新規作成)
Set cal = GetOrCreateCalendar(pj, “Standard”)

‘ 稼働日定義の反映
For i = 2 To lastRow
Dim holidayDate As Date
holidayDate = ws.Cells(i, 1).Value

‘ 特定の日に休日を割り当て(Working = False)
‘ ※BaseCalendarのException管理はここが肝
cal.Exceptions.Add Type:=1, Start:=holidayDate, Finish:=holidayDate
Next i

Application.ScreenUpdating = True
MsgBox “同期完了。”
End Sub

Private Function GetOrCreateCalendar(pj As Project, calName As String) As Calendar
On Error Resume Next
Set GetOrCreateCalendar = pj.BaseCalendars(calName)
If GetOrCreateCalendar Is Nothing Then
Set GetOrCreateCalendar = pj.BaseCalendars.Add(calName)
End If
End Function

3. チーフアーキテクトの視点:限界を突破する技術

A. レガシー環境におけるパフォーマンス最適化

Projectのオブジェクトモデルは、`Exception`を大量に追加すると急激に処理が重くなる。もし100件以上の休日を扱う場合、一度`BaseCalendar`をXML等でエクスポートし、テキスト処理で置換して再インポートする手法も検討すべきだ。VBAのオブジェクト操作を介さない方が、圧倒的に速いケースがある。

B. Windows APIによる「異常系」のハンドリング

Projectがハングアップした場合、VBAの`On Error`だけでは制御不能になる。API呼び出し(`FindWindow`, `SendMessage`)を用いて、Projectのプロセス状態を監視し、応答がない場合は強制終了(`TerminateProcess`)するウォッチドッグ処理を組み込むのが、真にプロフェッショナルな設計だ。

C. データ整合性の担保

Excel側の休日リストには必ず「日付の重複チェック」と「休日名称のバリデーション」を組み込め。ProjectのAPIは、重複する`Exception`を登録しようとするとエラーを吐く。このエラーを握りつぶすのではなく、「なぜ重複が発生したか」をログ出力する設計が、システム管理者の工数を劇的に減らす。

結び:エンジニアリングの品格

「動けばいい」という考えは、やがてゴミの山を築く。
Projectのカレンダーを操作するということは、組織の「時間の定義」を操作するということだ。その重みを理解し、メモリとプロセス、そしてデータの整合性に魂を込めること。

それが、我々が守るべきエンジニアリングの品格である。
次は、このカレンダー設定をベースとした「工数進捗の自動推論エンジン」について深掘りしよう。諸君の健闘を祈る。

タイトルとURLをコピーしました