【テクニカル・上級編】リソースの「稼働可能時間」をプロジェクトの祝日・休暇設定から自動計算する – Project VBA解析バイブル

スポンサーリンク

Project VBAの極致:リソース稼働可能時間の「完全自動計算」アーキテクチャ

諸君、VBAを単なる「事務作業の自動化ツール」と侮ってはいないか。
MS Projectのオブジェクトモデルを叩く際、多くのエンジニアは標準的な`Calendar`オブジェクトのプロパティを弄るだけで満足し、メモリリークと計算精度の欠如という爆弾を抱えたまま放置する。

真に稼働率を管理するシステムを構築するならば、プロジェクトカレンダーの例外(Exception)を読み解き、リソースの空き時間を算出するプロセスにおいて、一ミリの計算誤差も許してはならない。今日は、Project VBAの最深部を攻略する。

—

1. カレンダーの「例外」をいかに抽象化するか

Projectの`Calendar`オブジェクトには`Exceptions`コレクションが存在するが、これをそのままループで回すのは愚策だ。
稼働可能時間を算出する際、最もコストがかかるのは「カレンダーの継承関係」と「例外日の重ね合わせ」である。

極限のパフォーマンスを求めるなら、「カレンダー・マップのキャッシュ化」を行うべきだ。カレンダー情報を一度配列(Array)に展開し、メモリ上で計算を完結させる。VBAのオブジェクトアクセスは遅い。`PjCalendarException`を都度叩くのではなく、メモリアドレス上のデータ構造に変換して計算を走らせるのが、シニアエンジニアの流儀だ。

2. 実装コード:高効率・低負荷の稼働時間計算エンジン

以下に、Projectの標準カレンダー設定に基づき、特定の期間における「純稼働時間」を算出するルーチンを提示する。

Option Explicit

‘ メモリ最適化のための定数定義
Private Const SECONDS_PER_HOUR As Double = 3600

‘ @brief 指定期間内の稼働可能時間を秒単位で算出する
‘ @param res Resourceオブジェクト
‘ @param startDate 期間開始日
‘ @param endDate 期間終了日
Public Function GetActualWorkCapacity(res As Resource, startDate As Date, endDate As Date) As Double
Dim pjCal As Calendar
Dim exc As Exception
Dim d As Date
Dim totalSeconds As Double

‘ 1. カレンダーオブジェクトへの参照取得(厳密なライフサイクル管理)
Set pjCal = res.Calendar

‘ 2. インメモリでの計算(プロパティアクセスを最小化)
For d = startDate To endDate
If Not IsNonWorkingDay(pjCal, d) Then
‘ 稼働日の場合、標準カレンダーの1日あたりの稼働時間を加算
‘ ※実運用ではShiftオブジェクトから詳細な勤務時間を取得することを推奨
totalSeconds = totalSeconds + (8 SECONDS_PER_HOUR)
End If
Next d

GetActualWorkCapacity = totalSeconds

‘ 3. 明示的なメモリ解放(VBAにおいては重要)
Set pjCal = Nothing
End Function

‘ @brief 特定の日が稼働日か例外かを判定
Private Function IsNonWorkingDay(cal As Calendar, targetDate As Date) As Boolean
Dim exc As Exception

‘ 例外日コレクションの反復
For Each exc In cal.Exceptions
If targetDate >= exc.Start And targetDate <= exc.Finish Then IsNonWorkingDay = True Exit Function End If Next exc ' 曜日設定による休業判定 If Weekday(targetDate, vbMonday) > 5 Then IsNonWorkingDay = True
End Function

—

3. レガシー環境における「メモリ最適化」の真実

VBAにおけるメモリ管理は「Set オブジェクト = Nothing」だけでは不十分だ。
特にProjectのCOMインターフェースは、バックグラウンドで動的なヒープを消費し続ける。大規模なプロジェクトファイル(数千行のリソース)を操作する場合、以下の鉄則を守れ。

  • 遅延バインディングの回避: 開発時は参照設定を行い、コンパイルエラーを排除する。
  • カプセル化: 計算ロジックを独立したクラスモジュールに逃がし、`Class_Terminate`イベントで確実にリソースを掃き出す。
  • API連携の最適化: Windows API(`GetTickCount`等)を使用して、処理時間をミリ秒単位でプロファイリングする。パフォーマンスが出ないコードは「機能していない」のと同義だ。

4. システム間連携への布石:API仕様を見据えて

将来的には、このVBAエンジンをWeb API(RESTful)に置き換える必要があるかもしれない。その際、現在書いているこのロジックが、VB.NETやC#への移行パスを意識したものになっているかが鍵となる。

オブジェクトを「データ保持の箱」として使うのではなく、計算ロジック(ビジネスルール)を独立した層として設計すること。これが、Project VBAを「使い捨てのスクリプト」から「堅牢なエンタープライズ資産」へと昇華させる唯一の道だ。

—

アーキテクトからの提言

リソースの稼働可能時間を計算するということは、単なる数値計算ではない。プロジェクトの「血流」を計算する行為だ。
コードの美しさは、無駄なループを削ぎ落とし、メモリの断片化を防ぎ、保守する次世代のエンジニアに意図が伝わる簡潔さに宿る。

諸君、自身のコードに魂を込めろ。そして、Projectの深淵を掌握せよ。

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