プロジェクトのベースライン変更を逃さず記録!Project VBAで構築する「監査ログ出力」超入門
こんにちは!いつもプロジェクト管理や業務自動化の設計、お疲れ様です。
Microsoft Project(以下、MS Project)を現場で使っていると、こんな問題に直面したことはありませんか?
「気がついたら、プロジェクトの当初計画(ベースライン)が書き換わっている……。一体、誰が、いつ、何の目的で更新したんだろう?」
MS Projectは非常に強力な計画管理ツールですが、標準機能だけでは「誰がいつベースラインを保存したか」という変更履歴(監査ログ)を自動で残すことができません。プロジェクトのガバナンス(統制)を効かせるためには、この「ベースラインの設定履歴」を専用のデータベース(DB)や共有ログに自動蓄積する仕組みが不可欠です。
「難しそう……マクロの記録しかやったことがない自分にできるかな?」
大丈夫です。今回は、マクロの記録から一歩踏み出したいあなたに向けて、Project VBAを使ってベースラインの保存イベントを検知し、外部の管理データベース(またはログファイル)に監査ログを自動書き込みする仕組みを、基礎から本質まで丁寧に解説します。
ここをクリアすれば、Project VBAの基本とイベント処理の本質はバッチリ掴めますよ。さあ、一緒に一歩進んだ自動化の扉を開けてみましょう!
—
1. 「ベースライン監査」の全体像を見てみよう
コードを書く前に、まずは全体像をイメージしてみましょう。
今回は、MS Projectでユーザーが「ベースラインの保存」を実行した瞬間に、VBAがそれを横取り(インターセプト)し、自動的に裏側でログデータをデータベースへ送信する仕組みを作ります。
[ MS Project の操作 ]
│
▼ (ユーザーがベースラインを保存)
┌─────────────────────────────────────────┐
│ ① VBAのイベントハンドラが起動 │
│ ・「誰が」「いつ」「どのプロジェクトで」 │
│ ・「どのベースライン(0〜11)」を保存したか │
└─────────────────────────────────────────┘
│
▼ (ADOコネクションを確立)
┌─────────────────────────────────────────┐
│ ② データベース (Access / SQL Server 等) │
│ または、共有ログファイルへデータを書き込み │
└─────────────────────────────────────────┘
この仕組みを作ることで、「勝手に計画が書き換えられて、遅延の原因が分からなくなる」というトラブルを未然に防ぐことができます。
—
2. 準備:イベントを監視する「クラスモジュール」の魔法
MS Projectで「ベースラインが保存された瞬間」をキャッチするには、イベントという概念を使います。
一般的な標準モジュールにコードを書くだけでは、この「〜された瞬間」を捉えることができません。そこで、クラスモジュールという特別なモジュールを使用します。
ステップ 1: クラスモジュールの作成
1. MS Projectを開き、`Alt + F11` キーを押してVBAエディタ(VBE)を開きます。
2. メニューの `挿入` -> `クラスモジュール` をクリックします。
3. 作成されたクラスモジュールの名前(オブジェクト名)を `EventClass` に変更します。
ステップ 2: イベント監視コードの記述
作成した `EventClass` に、以下のコードを貼り付けてください。
‘ ==========================================
‘ クラスモジュール名: EventClass
‘ 役割: MS Projectのイベント(ベースライン保存など)を監視する
‘ ==========================================
Option Explicit
‘ MS Projectのアプリケーションオブジェクトをイベント付きで宣言します
Public WithEvents AppListener As MSProject.Application
‘ ————————————————–
‘ イベント: プロジェクトのベースラインが保存される直前に自動実行される
‘ ————————————————–
Private Sub AppListener_ProjectBeforeBaselineSave( _
ByVal pj As Project, _
ByVal Baseline As PjBaseline, _
ByVal AllTasks As Boolean, _
ByVal RollupToSummary As Boolean, _
ByVal RollupFromSubtasks As Boolean, _
Cancel As Boolean)
Dim userName As String
Dim projectName As String
Dim baselineName As String
Dim timestamp As String
On Error GoTo ErrorHandler
‘ 1. ログに必要な情報を収集する
userName = Environ(“USERNAME”) ‘ Windowsのログインユーザー名
projectName = pj.Name ‘ プロジェクトファイル名
timestamp = Format(Now, “yyyy-MM-dd HH:mm:ss”)
‘ 保存されたベースラインの種類を判別
baselineName = GetBaselineName(Baseline)
‘ 2. データベース(またはログ)への書き込み処理を呼び出す
‘ ※このあと作成する標準モジュールの関数を呼び出します
Call WriteAuditLog(timestamp, userName, projectName, baselineName)
Exit Sub
ErrorHandler:
‘ エラーが発生しても、ユーザーの保存処理自体を邪魔しないように安全に処理します
MsgBox “ベースライン監査ログの記録中にエラーが発生しました: ” & Err.Description, vbExclamation, “システム警告”
End Sub
‘ ————————————————–
‘ ヘルパー関数: ベースライン定数をわかりやすい文字列に変換
‘ ————————————————–
Private Function GetBaselineName(ByVal Baseline As PjBaseline) As String
Select Case Baseline
Case pjBaseline: GetBaselineName = “ベースライン (無印)”
Case pjBaseline1: GetBaselineName = “ベースライン 1”
Case pjBaseline2: GetBaselineName = “ベースライン 2”
Case pjBaseline3: GetBaselineName = “ベースライン 3”
Case pjBaseline4: GetBaselineName = “ベースライン 4”
Case pjBaseline5: GetBaselineName = “ベースライン 5”
Case pjBaseline6: GetBaselineName = “ベースライン 6”
Case pjBaseline7: GetBaselineName = “ベースライン 7”
Case pjBaseline8: GetBaselineName = “ベースライン 8”
Case pjBaseline9: GetBaselineName = “ベースライン 9”
Case pjBaseline10: GetBaselineName = “ベースライン 10”
Case Else: GetBaselineName = “未知のベースライン”
End Select
End Function
—
3. 実装:データベース(またはファイル)へログを書き込む
次に、実際にデータを保存する「送信機」の部分を作ります。
ここでは実務で最もよく使われるADO(ActiveX Data Objects)という技術を使って、Accessのデータベース(`.accdb`)に直接ログを書き込むコードを紹介します。
「データベースが手元にないよ!」という方のために、データベースが見つからない場合は自動的に共有テキスト(CSV)ログにフォールバック(代替切り替え)する、実務直結の超親切設計にしています。
ステップ 3: 標準モジュールの作成
1. VBEのメニューから `挿入` -> `標準モジュール` をクリックします。
2. 作成されたモジュールに、以下のコードを貼り付けてください。
‘ ==========================================
‘ 標準モジュール名: ModAuditLogger
‘ 役割: 監査ログをデータベースまたはファイルへ物理的に書き込む
‘ ==========================================
Option Explicit
‘ クラスインスタンスを保持するためのグローバル変数
Dim myAppListener As EventClass
‘ ————————————————–
‘ 仕組みの起動:プロジェクト起動時などに実行する
‘ ————————————————–
Public Sub InitializeAuditLogger()
Set myAppListener = New EventClass
Set myAppListener.AppListener = MSProject.Application
‘ イミディエイトウィンドウにログを出力(デバッグ用)
Debug.Print “ベースライン監査システムが起動しました。”
End Sub
‘ ————————————————–
‘ 仕組みの停止:監視を終了する場合に実行する
‘ ————————————————–
Public Sub TerminateAuditLogger()
Set myAppListener = Nothing
Debug.Print “ベースライン監査システムを停止しました。”
End Sub
‘ ————————————————–
‘ コア処理: 監査ログの書き込み
‘ ————————————————–
Public Sub WriteAuditLog(ByVal ts As String, ByVal user As String, ByVal proj As String, ByVal baseNum As String)
Dim dbPath As String
Dim connString As String
Dim sql As String
‘ 【設定】ログを保存するAccessデータベースのパス
‘ ※ご自身の環境に合わせて変更してください。
dbPath = “C:\AuditLogs\ProjectAudit.accdb”
‘ 簡易的なエラーハンドリング
On Error GoTo FallbackToFile
‘ 1. データベース接続用のコネクション文字列
connString = “Provider=Microsoft.ACE.OLEDB.12.0;Data Source=” & dbPath & “;”
‘ 2. ADOオブジェクトの作成(遅延バインディング)
Dim conn As Object
Set conn = CreateObject(“ADODB.Connection”)
‘ 3. DBオープンとSQL(データ挿入)の実行
conn.Open connString
sql = “INSERT INTO BaselineLogs (LogTimestamp, UserName, ProjectName, BaselineName) ” & _
“VALUES (‘” & ts & “‘, ‘” & user & “‘, ‘” & proj & “‘, ‘” & baseNum & “‘);”
conn.Execute sql
conn.Close
Set conn = Nothing
Debug.Print “DBへのログ保存に成功しました。”
Exit Sub
FallbackToFile:
‘ — DBへの接続に失敗した場合、テキストログへの書き込みに切り替えます —
Debug.Print “DB接続失敗のため、テキストログへの書き込みを実行します: ” & Err.Description
Call WriteLogToFile(ts, user, proj, baseNum)
End Sub
‘ ————————————————–
‘ サブ処理: テキストファイル(CSV)へのフォールバック書き込み
‘ ————————————————–
Private Sub WriteLogToFile(ByVal ts As String, ByVal user As String, ByVal proj As String, ByVal baseNum As String)
Dim logFilePath As String
Dim fileNum As Integer
‘ 実行中のプロジェクトと同じフォルダ、またはデスクトップにログを出力
logFilePath = Environ(“USERPROFILE”) & “\Desktop\project_baseline_audit.log”
fileNum = FreeFile
‘ 追記モードでファイルを開き、カンマ区切りで書き込む
Open logFilePath For Append As #fileNum
Print #fileNum, ts & “,” & user & “,” & proj & “,” & baseNum
Close #fileNum
Debug.Print “テキストログへの書き込みが完了しました: ” & logFilePath
End Sub
—
4. 動かしてみよう!運用のステップ
「コードは貼ったけれど、どうやって動かすの?」と思いますよね。
このシステムを有効化するには、MS Projectが起動したときに自動で上記の `InitializeAuditLogger` を実行させてあげる必要があります。
自動起動の設定
一番簡単な方法は、MS Projectの「スタートアップ」イベントを利用することです。
1. VBEの左側にあるプロジェクトブラウザから、`ThisProject`(または `ThisProject (Global.MPT)`)をダブルクリックします。
2. 以下のコードを貼り付けます。
‘ ==========================================
‘ ThisProject モジュール
‘ 役割: プロジェクトファイルが開いたときに自動で監視を開始する
‘ ==========================================
Private Sub Project_Open(ByVal pj As Project)
‘ 監査ログシステムを起動します
Call InitializeAuditLogger
End Sub
これで準備完了です!
一度プロジェクトファイルを保存して開き直すか、手動で `InitializeAuditLogger` の中にカーソルを置いて `F5` キーを押して実行してみてください。
その状態で、MS Projectのメニューから 「プロジェクト」タブ -> 「ベースラインの設定」 を行ってみましょう。
裏側で自動的にデスクトップ(または指定したDB)に `project_baseline_audit.log` というファイルが生成され、以下のような美しいログが一行追加されているはずです!
2023-10-25 14:30:15,yamada_tarou,新システム開発計画.mpp,ベースライン (無印)
—
5. 陥りやすいエラーと、プロが教える回避のコツ
マクロの記録から脱却しようとする際、いくつかの「見えない壁」にぶつかることがあります。先輩として、あらかじめ回避策を伝授しておきますね。
① 「イベントが動かない!」の壁
「マクロを有効にしたのに、ベースラインを保存してもログが残らない……」
これはVBA開発で最もよくある罠の一つです。
- 原因: VBAの中でエラーが発生して処理が途中で止まると、メモリに常駐していた `myAppListener`(イベントの監視役)が消滅してしまうことがあります。
- 対策: VBEのイミディエイトウィンドウで `InitializeAuditLogger` をもう一度手動実行してみてください。また、本番運用では、不意のエラーで監視が途切れないよう、コード内に `On Error Resume Next` ではなく、適切なエラーハンドリング(`On Error GoTo`)を配置することが不可欠です。
② 「データベースの接続エラー(プロバイダーが見つかりません)」
- 原因: 64bit版のMS Project(Office)を使っている場合、接続文字列のプロバイダー(`Microsoft.ACE.OLEDB.12.0` など)がPCにインストールされていないことがあります。
- 対策: 実務で最も堅牢なアプローチは、今回のコードのように「DB接続に失敗したら、即座に共有フォルダのテキストファイル(CSV)への書き込みに切り替える(フォールバック)」設計にしておくことです。システムを完全に止めない工夫こそが、プロの設計思想です。
—
まとめ
お疲れ様でした!
一見難しそうな「データベース連携」や「監査ログの自動出力」も、分解してみると、
1. イベントを検知する(クラスモジュール)
2. 情報を集めて整理する(変数処理)
3. 外部に届ける(ADO接続 or テキスト出力)
という3つのシンプルなステップで成り立っていることが分かったかと思います。
これが作れるようになると、MS Projectを単なる「スケジュール引き」の道具から、「組織のガバナンスを守る高度な業務システム」へと進化させることができます。
「ここをクリアすれば、Project VBAの基本はバッチリですよ。」
ぜひ今回のコードをベースに、職場の環境に合わせたログシステムを作ってみてください。あなたのエンジニアとしてのスキルが、また一歩大きく前進することを応援しています!
