【Project VBA】プロジェクトのベースライン設定履歴を専用管理DBへ蓄積する監査ログ機能の実装
エンタープライズ環境における大規模プロジェクト管理において、最も恐ろしい事態の一つは「いつの間にかベースラインが書き換えられ、進捗の比較基準が失われていること」だ。
誰が、いつ、どのバージョン(Baseline 0〜10)の基準を再設定したのか。この変更履歴のトレーサビリティが担保されていなければ、プロジェクトガバナンスは形骸化する。標準機能のProject単体では、上書きされたベースラインの「過去の履歴」を時系列で追うことは困難である。
今回は、Project VBAとADO(ActiveX Data Objects)を駆使し、ベースライン設定のアクションをフックして、外部の監査用データベース(SQLite / Access等)へ自動的にログを永続化するプロダクションコードを授与する。
—
1. 堅牢な設計思想:なぜ標準機能だけでは不十分なのか
プロジェクトマネージャー(PM)やPMOが勝手にベースラインを再設定(リセット)してしまうと、アーンド・バリュー分析(EVM)の数値が歪み、経営陣への報告が破綻する。
これを防ぐためのアーキテクチャ上のポイントは以下の通りだ。
1. イベントプロシージャの正確な捕捉
Projectのイベント(`ProjectBeforeBaselineSave`等)をフックし、処理の割り込みと監査データの抽出を行う。
2. トランザクション制御と疎結合なDB接続
VBAから外部DBへ書き込む際、ネットワークの瞬断やファイルロックでVBA側がエラー落ちしてはならない。エラーハンドリングを徹底し、Project本体の操作性を阻害しない設計にする。
3. メタデータの完全性
単に「いつ設定したか」だけでなく、「誰が(Windowsユーザー名/Projectアカウント)」「どのベースライン番号か」「総工数や総コストの現状値」をスナップショットとして同時記録する。
—
2. 全体アーキテクチャと実装の流れ
[MS Project 側]
└─ ユーザーがベースラインを設定
└─ Application_ProjectBeforeBaselineSave イベント発火
├─ プロジェクトメタデータ(工数・コスト等)の収集
└─ ADO経由で外部管理DB(監査ログ)へINSERT
今回は汎用性を考慮し、接続先として最も手軽かつ堅牢な Microsoft Access (.accdb) または SQLite を想定したADO接続コードを提示する(※実務ではSQL ServerやOracleへの接続文字列に変更するだけでそのまま流用可能)。
—
3. プロダクションコード実装
このコードは、MS Projectの `ThisProject` モジュール および 標準モジュール に配置する。
① イベントハンドラ(ThisProject モジュール)
プロジェクト全体のイベントを監視し、ベースライン保存の瞬間に割り込み処理を行う。
‘ Option Explicitを強制し、変数の宣言落ちを防ぐ
Option Explicit
‘ 監査ロジッククラスのインスタンスを保持
Private objAuditLogger As CBaselineAuditLogger
Private Sub Project_Open(ByVal Sv As Project)
‘ プロジェクトオープン時にロガーを初期化
Set objAuditLogger = New CBaselineAuditLogger
Call objAuditLogger.Initialize
End Sub
‘ ベースラインが保存される直前に発火するイベント
Private Sub Application_ProjectBeforeBaselineSave(ByVal Sv As Project, ByVal WhichBaseline As PjBaselineType, ByVal AllTasks As Boolean, Cancel As Boolean)
On Error GoTo ErrorHandler
‘ 監査ログ記録処理の実行
If objAuditLogger Is Nothing Then
Set objAuditLogger = New CBaselineAuditLogger
End If
objAuditLogger.RecordBaselineAction Sv, WhichBaseline, AllTasks
Exit Sub
ErrorHandler:
‘ 監査ログの失敗によってプロジェクトの保存自体をクラッシュさせないためのフェイルセーフ
MsgBox “ベースライン監査ログの記録中にエラーが発生しました。” & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “監査ログシステムエラー”
‘ 必要に応じて Cancel = True で保存をキャンセルする設計も可
End Sub
Private Sub Project_Close(ByVal Sv As Project)
Set objAuditLogger = Nothing
End Sub
② 監査ログ処理クラス(クラスモジュール:`CBaselineAuditLogger`)
データベースへの接続、データの抽出、SQLインジェクション対策を施したクエリ実行をカプセル化する。
Option Explicit
Private Const DB_PATH As String = “C:\ProjectGovernance\AuditLogs.accdb”
Private Const TABLE_NAME As String = “T_BaselineAuditLog”
Public Sub Initialize()
‘ 必要に応じた初期化処理(接続テスト等)
End Sub
Public Sub RecordBaselineAction(ByVal proj As Project, ByVal baselineType As PjBaselineType, ByVal allTasks As Boolean)
Dim conn As Object
Dim cmd As Object
Dim connString As String
‘ ADOコネクションの生成
Set conn = CreateObject(“ADODB.Connection”)
Set cmd = CreateObject(“ADODB.Command”)
‘ ConnectionStringの設定 (Accessの例。SQL Serverの場合はProviderを変更)
connString = “Provider=Microsoft.ACE.OLEDB.12.0;Data Source=” & DB_PATH & “;Persist Security Info=False;”
conn.Open connString
Set cmd.ActiveConnection = conn
cmd.CommandType = 1 ‘ adCmdText
‘ パラメータ化クエリによるSQLインジェクション完全防御と型安全性の確保
cmd.CommandText = “INSERT INTO ” & TABLE_NAME & ” ” & _
“(ProjectName, BaselineNumber, TargetScope, TotalWork, TotalCost, SetBy, SetDate) ” & _
“VALUES (?, ?, ?, ?, ?, ?, ?)”
‘ パラメータの追加
cmd.Parameters.Append cmd.CreateParameter(“p1”, 200, 1, 255, proj.Name) ‘ VarChar
cmd.Parameters.Append cmd.CreateParameter(“p2”, 3, 1, , CInt(baselineType)) ‘ Integer
cmd.Parameters.Append cmd.CreateParameter(“p3”, 200, 1, 50, IIf(allTasks, “All Tasks”, “Selected Tasks”))
cmd.Parameters.Append cmd.CreateParameter(“p4”, 5, 1, , proj.ProjectSummaryTask.Work) ‘ Double (工数)
cmd.Parameters.Append cmd.CreateParameter(“p5”, 6, 1, , proj.ProjectSummaryTask.Cost) ‘ Currency (コスト)
cmd.Parameters.Append cmd.CreateParameter(“p6”, 200, 1, 100, Environ(“USERNAME”)) ‘ Windowsユーザー名
cmd.Parameters.Append cmd.CreateParameter(“p7”, 135, 1, , Now) ‘ Date/Time
‘ 実行
cmd.Execute
‘ クリーンアップ
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
—
4. データベース側の要件(スキーマ設計)
上記コードで連携するデータベース側には、あらかじめ以下のスキーマ(テーブル構造)を用意しておく必要がある。
CREATE TABLE T_BaselineAuditLog (
LogID AUTOINCREMENT PRIMARY KEY,
ProjectName TEXT(255) NOT NULL,
BaselineNumber INT NOT NULL, — 0〜10 または -1(Baseline)
TargetScope TEXT(50) NOT NULL, — 全体か選択タスクか
TotalWork FLOAT NOT NULL, — 設定時点の総工数
TotalCost CURRENCY NOT NULL, — 設定時点の総コスト
SetBy TEXT(100) NOT NULL, — 操作したWindowsアカウント
SetDate DATETIME NOT NULL — 操作日時
);
—
5. 実務運用のためのチーフアーキテクトからの助言
1. ファイルパスの動的解決
サンプルコードでは `DB_PATH` をハードコーディングしているが、実務ではアドイン( `.ppa` / `.xlam` )のインストールフォルダや、ネットワーク上の共有リポジトリパスをレジストリやINIファイルから動的に取得する設計にすべきだ。
2. エラー時のフェイルセーフ設計
監査ログの書き込みに失敗したからといって、プロジェクト全体のベースライン保存処理自体を止めてしまうのは業務継続性の観点から好ましくない。今回のコードのように、エラーはキャッチしてログ出力(またはローカルテキストへのフォールバック保存)しつつ、ユーザーの作業を阻害しない配慮が必要不可欠である。
3. VBEパスワード保護の徹底
ガバナンスツールである以上、担当者がVBAコードを書き換えてログ記録をバイパスできては意味がない。プロジェクトファイルまたはアドインファイルには必ずVBEのプロジェクトロック(パスワード保護)をかけ、権限者以外の改ざんを防ぐこと。
組織のルールを「人の意識」だけに頼るな。システム構造とコードの力で、不正やヒューマンエラーが入り込む余地を完全に断つことこそが、真の業務自動化エンジニアの仕事である。
