【テクニカル・上級編】【中級者向け】プロジェクトの「保存」イベントをフックして、変更履歴をCSVログとして外部出力する監査機能 – Project VBA解析バイブル

スポンサーリンク

プロジェクトの「保存」を掌握する:MS Project VBAによる監査ログ自動生成の極意

MS Projectは、単なるスケジュール管理ツールではない。それは組織の「血流」を可視化するデータベースであり、プロジェクトマネジメントにおいては、その変更履歴こそが資産である。

しかし、標準機能の「ベースライン」だけでは、誰が、いつ、どのような意思でそのプロジェクトファイルを保存したのかという「メタな履歴」までは追えない。シニアエンジニアならば、この「行間」をシステム化する義務がある。

本稿では、Project VBAのイベント駆動アーキテクチャを駆使し、保存イベントをフックして外部CSVへ監査ログを書き出す堅牢な実装を解説する。

1. アーキテクチャの要諦:Applicationイベントのライフサイクル

VBAにおけるイベントフックは、`ThisProject` モジュールではなく、`Class Module` を用いた「イベントシンク」で行うのが定石だ。これにより、アプリケーションのライフサイクル全体を監視対象とする。

ここで重要なのは、「オブジェクトの明示的解放」「エラーハンドリングの不可分性」である。中途半端なイベントハンドラは、Projectのフリーズやメモリリークの温床となる。

2. 実装:監査ログ出力クラスの実装

まず、`clsAppEvents` というクラスモジュールを作成し、以下のコードを記述する。

‘ クラスモジュール: clsAppEvents
Option Explicit

Private WithEvents App As MSProject.Application

‘ コンストラクタでApplicationをバインド
Public Sub Initialize(ByVal appInstance As MSProject.Application)
Set App = appInstance
End Sub

‘ 【核心】BeforeSaveイベントをフック
Private Sub App_ProjectBeforeSave(ByVal pj As Project, ByVal SaveAsUi As Boolean, Cancel As Boolean)
On Error GoTo ErrorHandler

Dim logPath As String
Dim fso As Object
Dim ts As Object

‘ ログファイルのパス(ネットワークパスやローカルの監査用ディレクトリを指定)
logPath = “C:\AuditLogs\ProjectChanges.csv”

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set ts = fso.OpenTextFile(logPath, 8, True) ‘ 8 = ForAppending

‘ 監査ログの出力: タイムスタンプ, プロジェクト名, ユーザー名, 保存タイプ
ts.WriteLine Now & “,” & pj.Name & “,” & Environ(“USERNAME”) & “,” & IIf(SaveAsUi, “SaveAs”, “Save”)

ts.Close

CleanExit:
Set ts = Nothing
Set fso = Nothing
Exit Sub

ErrorHandler:
‘ 監査ログの失敗で業務を止めてはならないが、開発者には通知すべき
Debug.Print “Audit Error: ” & Err.Description
Resume CleanExit
End Sub

3. イベントの起動とメモリ管理

このクラスを有効化するには、`Auto_Open` マクロなどでグローバル変数として保持する必要がある。ここで、オブジェクトのスコープ管理が極めて重要になる。

‘ 標準モジュール: modEntry
Option Explicit

Public AppHandler As clsAppEvents ‘ プロセス間生存させる

Public Sub Auto_Open()
Set AppHandler = New clsAppEvents
AppHandler.Initialize Application
End Sub

4. シニアエンジニアが意識すべき「極限の知見」

① 非同期処理の限界とCSVロック

上記のコードは `OpenTextFile` を使用しているが、大規模環境では複数ユーザーが同時に保存を行うと競合(ロック)が発生する。これを回避するには、`Windows API` の `GetTickCount` や `Sleep` を利用した待機ロジックを組み込むか、書き込み専用のキューイング・サービスを別プロセスで起動するのが賢明だ。

② メモリリークを許容しない

VBAはガベージコレクションが極めて脆弱である。`Set fso = Nothing` を怠れば、連続してプロジェクトを開閉する環境では、Projectインスタンスのメモリ使用量が肥大化する。必ず `Finally` ブロックに近い `CleanExit` 構造を徹底すること。

③ 監査の「真正性」の確保

このログはあくまでクライアントサイドでの記録である。より厳格な監査が必要な場合、VBAから直接 `ADO` (ActiveX Data Objects) を介して、SQL Server等のデータベースへ書き出すアーキテクチャへ昇華させるべきだ。CSVは改ざんが可能であるという前提を忘れてはならない。

結びに代えて

「保存」という行為は、プロジェクトにおいて最も重要な意思決定の断面である。その一瞬をコードで捕捉し、可視化することは、エンジニアリングにおける「説明責任(Accountability)」を全うすることに他ならない。

この記事を読んだ諸君には、単なる機能実装で満足せず、システム全体の安定稼働と、その先にいる組織のガバナンスまでを見通した設計を期待する。VBAという古き良き言語は、使い手次第で最強の監査官にも、最凶の破壊者にもなり得るのだから。

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