【実務・中級編】リソースの「カレンダー例外」をExcelの休日リストから一括適用する高速化処理 – Project VBA解析バイブル

スポンサーリンク

Project VBAの闇を照らす:数千件の「カレンダー例外」を瞬時に叩き込む極限最適化術

Project VBAにおけるリソース管理は、多くのエンジニアが「泥沼」に足を取られる領域だ。特に、Excel上の休日リストを`Resource.Calendar.Exceptions`へ逐次反映させる処理。これを愚直にループで回せば、数千件のデータで処理は重鎮化し、最悪の場合、MS Project自体が「応答なし」の墓場へと消える。

なぜ、あなたのコードは遅いのか。答えはシンプルだ。「GUIを介したDOM操作のオーバーヘッド」と「不必要な再計算の発生」を放置しているからだ。

今回は、数秒で数千件の例外を反映させる、プロダクションレベルの「高速更新アーキテクチャ」を伝授する。

—

1. なぜ「愚直なループ」は死を招くのか

多くの初心者が書くコードは、以下の構造に陥っている。

‘ 【アンチパターン】絶対にやってはいけない処理
For Each row In holidayRange
‘ 毎回リソースオブジェクトを探し、例外を追加し、更新イベントを走らせる
res.Calendar.Exceptions.Add Type:=pjExceptionTypeWorking, Start:=d, Finish:=d
Next

このコードの敗因は二つある。
1. オブジェクトの再探索: ループのたびにCOMインターフェースを介したオブジェクト解決が行われる。
2. 再計算の連鎖: `Exceptions.Add`が実行されるたびに、MS Projectのスケジュールエンジンが再計算を試みる。数千回繰り返せば、CPUは悲鳴を上げる。

—

2. 極限の高速化:最適化のロジック

高速化の鍵は、「計算エンジンの凍結」と「オブジェクト参照のキャッシュ化」にある。以下の戦術を実装に組み込む。

1. CalculationModeのオフ: 処理中はプロジェクトの自動再計算を停止し、処理後に一括で再計算させる。
2. オブジェクトの事前保持: `Resource`オブジェクトへの参照をループ外で確定させる。
3. エラーハンドリングの堅牢化: 休日が重複した場合の例外処理をスマートに行う。

—

3. 実装コード:プロダクション・グレードの高速処理

以下のコードは、保守性と実行速度を両立させた「現場で使える」設計だ。

Option Explicit

‘ ———————————————————
‘ リソースカレンダー例外の一括登録エンジン
‘ ———————————————————
Public Sub BatchUpdateResourceExceptions(resourceName As String, holidayRange As Range)
Dim proj As Project
Dim res As Resource
Dim cell As Range
Dim calcMode As Long

Set proj = ActiveProject

‘ 1. 計算モードを一時停止し、パフォーマンスを最大化
calcMode = proj.Calculation
proj.Calculation = pjManual

On Error GoTo Cleanup

‘ 2. リソースの特定(高速化のため事前にオブジェクトを取得)
Set res = proj.Resources(resourceName)

‘ 3. 休日リストを走査(Rangeの値を配列に読み込むとさらに高速化可能)
For Each cell In holidayRange
If IsDate(cell.Value) Then
‘ 重複チェック等のバリデーションをここに組み込む
AddExceptionToCalendar res, cell.Value
End If
Next cell

Cleanup:
‘ 4. 必ず計算モードを復旧させる(重要)
proj.Calculation = calcMode
If Err.Number <> 0 Then MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub

Private Sub AddExceptionToCalendar(res As Resource, holidayDate As Date)
On Error Resume Next ‘ 重複追加によるエラーを回避
res.Calendar.Exceptions.Add Type:=pjExceptionTypeWorking, _
Start:=holidayDate, _
Finish:=holidayDate
On Error GoTo 0
End Sub

—

4. 現場のアーキテクトが語る「注意点」

ファイル連携の罠

Excelの休日リストは「日付型」であることを保証せよ。`Range`の値をそのまま突っ込むと、書式設定によっては`Variant`型が文字列として解釈され、Project側で型変換エラーを引き起こす。`IsDate()`でのバリデーションは必須だ。

データベース連携の視点

もし休日がSQL Server等の外部データベースに格納されているなら、Excelを介さずADOを用いて直接RecordSetとして取得し、それをメモリ上で配列(`Variant Array`)に展開せよ。セルへのアクセス(`Range.Value`)は、VBAにおける最大の遅延要因の一つだ。

保守性の担保

このコードをモジュール化する際は、`ResourceName`や`Range`を引数化し、特定のプロジェクトファイルに依存しない「ライブラリ」として管理せよ。そうすることで、他のプロジェクトへの転用が容易になり、技術負債の蓄積を防げる。

—

最後に:なぜこのコードか

私が提供したこの設計は、単に「速い」だけではない。`CalculationMode`を制御し、エラーを握りつぶさずに適切に管理する。これは、「ツールが動くこと」と「ツールが信頼できること」の間にある深い溝を埋めるための作法だ。

自動化とは、単なるコード書きではない。業務のボトルネックを物理的に破壊し、エンジニアとしての時間を創出する行為である。このコードをあなたのプロジェクトに実装し、数千件の処理が終わる瞬間の「静寂」を体感してほしい。それが、プロの仕事だ。

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