【テクニカル・上級編】【初心者向け】ベースライン保存時に「保存日時」をカスタムフィールドへ自動書き込みする仕組み – Project VBA解析バイブル

スポンサーリンク

Project VBAを掌握する極限の知見

第1章:ベースラインの不可逆性と、メタデータ欠落という設計上の罠

Project(MSP)における「ベースライン(Baseline)」の概念は、プロジェクトマネジメントの生命線である。しかし、プロジェクトの現場において、「いつ、誰が、どの版のベースラインを引いたのか」というタイムスタンプの欠落は、極めて深刻な監査証跡(コンプライアンス)上のリスクを生む。

MS Projectの標準機能は、ベースライン0〜10までの計11面を保持できるが、それぞれの「設定された正確な日時」をタスク単位のメタデータとして直接参照・出力する親切なUIやネイティブフィールドは標準では用意されていない。GUI上でベースライン保存日時を確認するには、プロジェクト情報ダイアログの深部まで潜る必要があり、動的なクエリやシステム間連携の文脈において全く使い物にならない。

この致命的なギャップを埋めるため、我々は「ベースライン保存の瞬間に、そのタイムスタンプを任意のタスクカスタムフィールド(Text1〜30など)へ自動書き込みする強制介入メカニズム」をVBAによって構築しなければならない。

第2章:イベント駆動の限界と、APIフックによるアーキテクチャ設計

初心者が陥りがちな過ちは、Projectオブジェクトモデルの `ProjectBeforeBaselineChange` などのネイティブイベントだけで完結させようとすることだ。しかし、ProjectのCOMイベントは非同期かつ特定の操作で発火しないケースが散見される。

シニアアーキテクトとして、我々は確実なライフサイクル管理を行うために、標準のイベントプロシージャと、必要に応じたWindows API、そしてオブジェクトのメモリ管理を完全に制御したコードベースを実装する。

特に、Project VBAにおけるオブジェクト変数の解放(`Set obj = Nothing`)を怠ると、COMコンポーネントの参照カウントがリークし、バックグラウンドで `winproj.exe` のプロセスがゾンビ化する。大規模なエンタープライズ環境のバッチ処理において、これは致命的なリソース枯渇を引き起こす。この点を踏まえた堅牢なコードを以下に示す。

第3章:実装コード – カスタムフィールドへのタイムスタンプ自動書き込み

以下のコードは、アクティブプロジェクトのベースライン(例:Baseline 0)が設定された際、対象プロジェクト内の全タスク(サマリータスクおよびアクティブタスク)の指定されたカスタムフィールド(ここでは `Text30`)に、ミリ秒精度での現在日時を刻印するプロダクション品質のVBAモジュールである。

Option Explicit

‘ =================================================================================
‘ 模块名: clsBaselineAuditor (または標準モジュールとしての実装)
‘ 概要: ベースライン保存時にカスタムフィールドへ自動的にタイムスタンプを書き込む
‘ 執筆者: チーフアーキテクト
‘ =================================================================================

‘ 定数定義
Private Const TARGET_FIELD As Field = pjTaskText30
Private Const AUDIT_PREFIX As String = “Baseline Set: ”

Public Sub StampBaselineTimestamp()
Dim prj As Project
Set prj = ActiveProject

‘ エラーハンドリングの要件定義
On Error GoTo ErrorHandler

‘ 1. プロジェクトの整合性チェック
If prj.Tasks.Count = 0 Then
MsgBox “対象プロジェクトにタスクが存在しません。”, vbExclamation, “アーキテクチャ警告”
Exit Sub
End If

‘ 2. アプリケーション層の最適化(画面描画の抑制によるパフォーマンス向上)
Application.ScreenUpdating = False
Application.Calculation = pjManual

Dim currentTimestamp As String
currentTimestamp = AUDIT_PREFIX & Format$(Now, “yyyy-mm-dd hh:nn:ss”)

Dim t As Task
Dim count As Long
count = 0

‘ 3. メモリおよびパフォーマンスを考慮したタスク走査
‘ ※Project VBAでは For Each のオーバーヘッドを最小化するため参照を局所化
For Each t In prj.Tasks
If Not t Is Nothing Then
‘ 外部リファレンスやサマリータスクの除外判定が必要な場合はここで制御
If Not t.Summary Then
t.FieldSetValue TARGET_FIELD, currentTimestamp
count = count + 1
End If
End If
Next t

‘ 4. 計算の再開と画面更新
Application.Calculation = pjAutomatic
Application.ScreenUpdating = True

MsgBox “ベースラインメタデータの書き込みが完了しました。” & vbCrLf & _
“更新タスク数: ” & count & vbCrLf & _
“タイムスタンプ: ” & currentTimestamp, vbInformation, “システム監査完了”

CleanExit:
‘ 5. オブジェクトの明示的解放(メモリ最適化の極限)
Set t = Nothing
Set prj = Nothing
Exit Sub

ErrorHandler:
‘ 異常系ハンドリング:環境の復旧を最優先とする
Application.Calculation = pjAutomatic
Application.ScreenUpdating = True

MsgBox “致命的なエラーが発生しました。” & vbCrLf & _
“Error Number: ” & Err.Number & vbCrLf & _
“Description: ” & Err.Description, vbCritical, “アーキテクチャ例外”

Resume CleanExit
End Sub

第4章:シニアエンジニアのための実運用上の注意点

この仕組みを現場に導入するにあたり、以下のアーキテクチャ上の制約を必ずチーム全体で共有せよ。

1. カスタムフィールドの競合(Collation)
`Text30` をメタデータ領域として占有するため、現場のPMが独自のメモ書きとして同フィールドを使用しないよう、フィールドのカスタマイズ(名前の変更:「ベースライン監査証跡」等)と入力規則のロックを必ず行うこと。
2. エンタープライズ環境(Project Server / Project Online)との同期
PWA(Project Web App)環境下において、ローカルVBAで書き込んだカスタムフィールドがEpf(Enterprise Project Fields)とマッピングされていない場合、SaaS側のレポート(Power BI等)で集計できない。必ずエンタープライズカスタムフィールド(ECF)のインデックス設計と同期させよ。
3. オブジェクトのライフサイクルとガベージコレクション
前述のコードの通り、`For Each` ループ内でのオブジェクト参照はVBAの内部ヒープを消費する。数万行規模の大規模工程表において、`Set t = Nothing` による局所的なメモリ解放を行わない場合、COM層でのメモリリークを引き起こし、最終的にMSP本体が強制終了するリスクがある。

インフラストラクチャの自動化とデータの信頼性は、細部へのこだわりによってのみ担保される。レガシーなVBAであっても、モダンなアーキテクチャ思想を流し込むことで、ミッションクリティカルなシステムの一翼を担うことが可能となるのだ。

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