こんにちは!プロジェクト管理の現場で「あ、今のタスクの変更、誰がいつやったんだっけ…?」と頭を抱えた経験はありませんか?
Excelのマクロなら何となく書けたけれど、Microsoft ProjectのVBA(Visual Basic for Applications)となると、途端にオブジェクトモデルの壁が立ちはだかり、マクロの記録も使えないからお手上げ……。そんな風に悩んでいませんか?
大丈夫。安心してください。今回は、「Project VBAにおけるイベント駆動の活用」という、実務で最高に役立つテクニックを一緒に解き明かしていきましょう。ここをクリアすれば、あなたのProject VBAのスキルは間違いなく「初学者」から「ワンランク上の自動化エンジニア」へとステップアップします。
優しく、そして本質的な部分までしっかりと解説していきますので、コーヒーでも飲みながらリラックスしてついてきてくださいね。
—
1. なぜ「イベント駆動」なのか?(マクロの記録からの脱却)
Excel VBAではお馴染みの「マクロの記録」。しかし、Microsoft Projectの世界では、ユーザーの操作を記録する機能がほとんど働きません。そのため、私たちは「自分でコードを書く」必要があります。
さらに、通常のVBAは「ボタンを押したら動く(手動)」という世界ですが、今回扱うイベント駆動(Event-Driven)は、ユーザーが何かをした瞬間(タスクを変更した、スケジュールを保存したなど)に、Project自身が自律的にコードを呼び出す仕組みです。
監査ログの自動化という実務の武器
今回作成するのは、「誰がいつ、どのタスクの何をどう変更したか」を自動で記録する監査ログです。
複数人で一つのスケジュールを管理していると、「勝手に工数が変えられている」「誰がこの期日を延ばしたんだ?」というトラブルが起きがちです。これをVBAのイベントで監視し、裏側で自動記録できれば、プロジェクトのガバナンスは劇的に向上します。
—
2. Project VBAのオブジェクトモデルと「ThisProject」の秘密
Excel VBAでコードを書くときは「標準モジュール」に書くことが多かったと思いますが、Projectのイベントを捉えるには「ThisProject(このプロジェクト)」モジュールという特別な場所を使います。
Projectのオブジェクト構造の基本
Project VBAの頂点には `Application` があり、その下に `Project` がいます。さらにその中に `Task` や `Resource` がぶら下がっています。
Application (アプリ全体)
└── Project (現在開いているプロジェクト)
├── Tasks (タスクの集合体)
│ └── Task (個別のタスク)
└── Resources (リソースの集合体)
└── Resource (個別のリソース)
今回は、この中の `Task` が変更された瞬間(BeforeTaskChangeイベント) を捕まえます。
—
3. 実装編:タスク変更を監視する監査ログコード
それでは、実際に動くコードを見ていきましょう。
以下のコードは、タスクの名前(Name)や期間(Duration)、開始日(Start)などが変更される直前にフックし、変更前の値と変更後の値をメッセージ(あるいは別ファイルやテキスト)に記録する仕組みの骨組みです。
ステップ1:ThisProjectモジュールへの記述
1. Projectを開き、`[Alt] + [F11]` キーを押してVBAエディタ(IDE)を開きます。
2. 左側のプロジェクトエクスプローラから、現在のプロジェクト(例:`VBAProject (プロジェクト1)`)を展開し、`ThisProject` をダブルクリックして開きます。
3. 以下のコードをそのまま貼り付けてください。
‘ =====================================================================
‘ モジュール名: ThisProject
‘ 概要: タスクの変更イベントを検知し、監査ログを記録する
‘ =====================================================================
‘ WithEventsキーワードを使い、Project全体のアプリケーションイベントを監視します
Private WithEvents App As Application
‘ プロジェクトが開かれたときにイベント監視を有効化する
Private Sub Project_Open(ByVal MyProject As Project)
Set App = Pj.Application
MsgBox “監査ログ監視システムが稼働を開始しました。”, vbInformation, “System Ready”
End Sub
‘ タスクの変更が「確定する直前」に発火するイベント
Private Sub App_BeforeTaskChange(ByVal tsk As Task, ByVal Field As PjField, ByVal NewValue As Variant, Cancel As Boolean)
‘ tskがNothing(タスクが存在しない)または、まだ新規作成中の場合はスルー
If tsk Is Nothing Then Exit Sub
If tsk.Name = “” Then Exit Sub
Dim oldVal As Variant
Dim logMessage As String
Dim currentUser As String
‘ 変更前の値を取得(フィールドの種類によって分岐)
Select Case Field
Case pjTaskName
oldVal = tsk.Name
Case pjTaskDuration
oldVal = tsk.Duration / 480 ‘ Projectの内部単位(分)を日(Days)に変換する場合の処理例
Case pjTaskStart
oldVal = tsk.Start
Case pjTaskFinish
oldVal = tsk.Finish
Case Else
‘ 監視対象外のフィールドは処理しない
Exit Sub
End Select
‘ 簡易的にWindowsのログインユーザー名を取得
currentUser = Environ(“USERNAME”)
‘ ログメッセージの組み立て
logMessage = Format(Now, “yyyy/mm/dd hh:nn:ss”) & ” | ” & _
“ユーザー: ” & currentUser & ” | ” & _
“タスクID: ” & tsk.ID & ” (” & tsk.Name & “) | ” & _
“フィールドID: ” & Field & ” | ” & _
“変更前: [” & oldVal & “] ⇒ 変更後: [” & NewValue & “]”
イミディエイトウィンドウにログを出力
Debug.Print logMessage
‘ 【実務への応用ヒント】
‘ ここでTextStreamなどを使って、社内の共有サーバーにあるCSVファイルに
‘ logMessageを追記書き込み(Append)すれば、完璧な監査ログの完成です!
End Sub
—
4. ここでハマる!初心者が陥りやすい3つの罠
Project VBAでイベントを扱う際、多くの初学者が以下の「罠」にハマります。ここを知っておくだけで、開発スピードが3倍変わります。
罠1:イベントが全く発火しない!
- 原因: `Private WithEvents App As Application` を宣言し、`Project_Open` 内で `Set App = Pj.Application` を実行していますが、コードを最初に貼り付けた直後は `Project_Open` がまだ走っていません。
- 解決策: VBAエディタ内で `Project_Open` の中にカーソルを置き、上部メニューの「実行(Run)」>「サブプロシージャの実行」を押して一度手動でこの初期化処理を走らせるか、一度プロジェクトファイルを保存して開き直してください。
罠2:内部単位と表示単位のズレ(期間の罠)
- 原因: ProjectのVBAにおいて、タスクの期間(Duration)などの数値は、私たちが画面で見ている「日(days)」ではなく、内部的には「分(minutes)」で保持されています。(例:1日は通常480分)。
- 解決策: サンプルコードでも少し触れましたが、期間を扱う際は `480` で割るなどの単位変換の配慮を忘れないようにしましょう。これを忘れると、ログに「変更後: 480」と記録されてパニックになります。
罠3:無限ループやエラーによる無限ポップアップ
- 原因: イベントプロシージャの中でタスクのプロパティを書き換えるコード(例:`tsk.Name = …`)を書いてしまうと、「書き換え -> イベント発火 -> さらに書き換え -> イベント発火…」の無限地獄に陥り、Projectがフリーズします。
- 解決策: `BeforeTaskChange` はあくまで「読み取り(監視)」にとどめ、値を書き換える処理は原則として行わないのが鉄則です。
—
5. まとめと次のステップ
今回は、Project VBAにおけるイベント駆動の極意として、`BeforeTaskChange` を使った監査ログの基礎を解説しました。
- 標準モジュールではなく `ThisProject` モジュールを使うこと
- `WithEvents` を使ってアプリケーションの動きを監視すること
- 変更の「直前(Before)」を捉えることで、変更前後の比較ができること
この3つさえ押さえておけば、もうマクロの記録が使えないからといってProject VBAを恐れる必要はありません。
ここをクリアしたあなたなら、次は「ログをExcelファイルに自動出力する」「TeamsやSlackのWebhookに通知を飛ばす」といった、さらに高度な業務自動化への扉を開くことができるはずです。
ぜひ、あなたの現場のプロジェクト管理を、このコードでよりスマートに、より強固なものにアップデートしてみてくださいね。応援しています!
