【テクニカル・上級編】タスクの「カスタムフィールド」を利用した、依存関係の「理由」を記録する監査ログ – Project VBA解析バイブル

スポンサーリンク

意志なきタスクは負債である:Project VBAによる「依存理由の監査ログ」自動化の実装

プロジェクトマネジメントにおいて、WBSの依存関係(Predecessors)は単なる線ではない。それは「なぜこの順序でなければならないのか」という、意思決定の履歴そのものだ。

しかし、Projectの標準フィールドだけでは、この「なぜ」を記録できない。結果、数ヶ月後のレビューで「なぜこのタスクがブロックされているのか」を誰も説明できなくなり、レガシーな運用が泥沼化する。

今回は、Project VBAの深淵に触れつつ、タスクの依存関係に「理由」を付与し、カスタムフィールドへ自動的に監査ログを刻み込むアーキテクチャを提示する。

1. アーキテクチャの要諦:なぜ「カスタムフィールド」なのか

Projectの依存関係は `TaskDependencies` コレクションとして管理されるが、これには「理由」を保持するメタデータ領域が存在しない。

解決策は明確だ。
1. Text(カスタムフィールド)の利用: 任意のTextフィールド(例: `Text1`)を監査ログ用として定義する。
2. イベントドリブン・フック: `Project_TaskChange` イベントをフックし、依存関係が変更された瞬間にスタックトレースを記録する。
3. メモリの最適化: 巨大なプロジェクトファイルにおいて、COMオブジェクトの保持は自殺行為である。`Nothing` による解放と、スコープの厳密な管理が不可欠だ。

2. 実装:依存関係監査ログの自動追記エンジン

以下のコードは、タスクの依存関係が更新された際、その理由(あるいは変更者とタイムスタンプ)を `Text1` に追記する実用的なモジュールである。

‘ — Class: clsProjectMonitor —
‘ Projectのイベントをキャプチャし、依存関係の変更を監査する

Private Sub Project_TaskChange(ByVal tsk As Task, ByVal Field As PjField)
‘ 依存関係(Predecessors)が変更された場合のみトリガーする
If Field = pjTaskPredecessors Then
Call AuditDependencyChange(tsk)
End If
End Sub

Private Sub AuditDependencyChange(ByRef tsk As Task)
Dim strLog As String
Dim oldLog As String

‘ メモリ最適化: オブジェクトへの参照は最小限のスコープで
On Error Resume Next
oldLog = tsk.Text1
On Error GoTo 0

‘ 監査ログの生成(タイムスタンプ + ユーザー情報 + 依存先ID)
strLog = “[” & Now & “] Dependency Updated: ” & tsk.Predecessors & vbCrLf & _
“Reason: Manually Adjusted by ” & Application.UserName & vbCrLf & _
“—” & vbCrLf & oldLog

‘ 文字数制限の考慮: Text1は255文字制限があるため切り詰め処理を推奨
If Len(strLog) > 250 Then strLog = Left(strLog, 250)

tsk.Text1 = strLog

‘ 明示的なオブジェクト解放はVBAにおいて必須の作法
‘ 参照の循環を防ぐため、サブプロシージャ終了時にクリーンアップ
End Sub

3. レガシー環境を生き抜くための極限の知見

Windows APIによるログの永続化

もし監査ログが非常に重要で、Projectファイルの破損リスクを避ける必要がある場合は、VBAから `Kernel32.dll` の `WritePrivateProfileString` を呼び出し、外部のINIファイルやローカルのログサーバーへ書き出す設計に変更すべきだ。

‘ Win32 API宣言
Private Declare PtrSafe Function WritePrivateProfileString Lib “kernel32” Alias “WritePrivateProfileStringA” _
(ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long

パフォーマンスを殺さないための「遅延実行」

巨大なプロジェクトで `TaskChange` を多用すると、GUIがフリーズする。`Application.OnTime` を利用してログ書き込みを非同期化するか、あるいはフラグ管理によって「操作終了後の一括書き込み」を行うのが、シニアエンジニアの嗜みである。

4. 最後に:システムは「動く」だけでは不十分だ

この運用ツールを導入する最大の目的は、ログを溜めることではない。「後から見た時に、そのタスクの制約条件が論理的に証明されている状態」を作ることだ。

Project VBAは古い言語だが、その背後にあるCOMアーキテクチャを理解していれば、現代的なDevOpsのパイプラインの一部として十分に機能する。

システム管理者諸君、コードを書く前にまず「なぜ依存するのか」というプロセスの設計を磨いてほしい。技術は目的のための手段に過ぎない。しかし、その手段が極限まで洗練されている時、プロジェクトの成功率は劇的に向上する。


文責:Project VBAチーフアーキテクト

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