【Project VBA極限知見】MS ProjectのGit完全自動連携:XMLエクスポートと非同期コミットのアーキテクチャ
Microsoft Projectは、その堅牢なスケジュールエンジンと裏腹に、ファイルフォーマットの面では長年エンジニアを悩ませてきた。`.mpp`は実質的なブラックボックスであり、差分管理(Diff)が不可能なバイナリの塊である。そのため、複数人によるアジャイルな変更管理や、厳格な監査証跡が求められるエンタープライズ環境において、バージョン管理システム(Git等)との統合は長年の課題であった。
本稿では、MS Projectの保存イベントをトリガーに、プロジェクトデータを人間が読める構造化テキスト(XML)へダンプし、外部プロセスとしてGitコマンドを非同期かつサイレントに叩き込む、構成管理自動化の極限ソリューションを提示する。
—
1. アーキテクチャの全体像と設計思想
MS ProjectのVBA環境からGitを直接操作する場合、以下の致命的なボトルネックが存在する。
1. 同期処理によるUIのフリーズ: Gitのコミットプロセス(特に大容量リポジトリやネットワークフック時)を同期実行すると、Project側のGUIが固まり、ユーザー体験を著しく損なう。
2. バイナリの限界: `.mpp`をそのままGit管理しても、内部構造の差分を取れない。
3. オブジェクトのライフサイクル管理の欠如: VBAからCOMオブジェクトや外部シェルを乱暴に呼び出すと、メモリリークやゾンビプロセスの温床となる。
これらを解決するため、本アーキテクチャでは「イベントフック ➔ XMLエクスポート ➔ 非同期バッチ委譲」のパイプラインを採用する。VBAからは重いGit処理を直接行わず、VBScriptまたは独立したシェルスクリプトをキックしてバックグラウンドで処理を完結させる。
—
2. 実装コード:`ThisProject` クラスモジュール
以下のコードは、MS Projectのプロジェクトファイル(`.mpp`)に埋め込むイベントハンドラである。`FileSave` または `FileSaveAs` イベントをキャッチし、自動的にXMLへのエクスポートとGitへのコミットチェーンを起動する。
‘ Option Explicitを強制し、暗黙の変数の宣言を防ぐ(エンジニアの基本)
Option Explicit
‘—————————————————————-
ギ
‘ イベントドリブン・Git自動連携モジュール
‘—————————————————————-
Private Sub Project_BeforeSave(ByVal AS_Project As Project)
On Error GoTo ErrorHandler
Dim xmlPath As String
Dim repoPath As String
Dim fso As Object
‘ 1. リポジトリパスの特定(Projectファイルと同階層を想定)
If AS_Project.FullName = “” Then
‘ 未保存の新規ファイルの場合はスキップ
Exit Sub
End If
Set fso = CreateObject(“Scripting.FileSystemObject”)
repoPath = fso.GetParentFolderName(AS_Project.FullName)
‘ 2. XML形式でのエクスポート (MS Project標準のSaveAsを用いる)
‘ パフォーマンスと可読性を考慮し、MSPDI (Microsoft Project Data Interchange) XML形式を指定
Dim targetFileName As String
targetFileName = fso.GetBaseName(AS_Project.Name) & “.xml”
xmlPath = fso.BuildPath(repoPath, targetFileName)
‘ 既存の同名XMLを排他制御を考慮して上書きエクスポート
‘ 引数: FileName, FileFormat (pjXML = 23)
AS_Project.SaveAs FileName:=xmlPath, FileFormat:=pjXML
‘ 3. 非同期Gitコミットプロセスのキック
Call InvokeAsyncGitCommit(repoPath, targetFileName, AS_Project.Name)
CleanUp:
‘ 4. 厳格なメモリ解放(COMオブジェクトのゾンビ化を防ぐ)
Set fso = ExitObject(fso)
Exit Sub
ErrorHandler:
MsgBox “Git自動連携エラー: ” & Err.Description, vbCritical, “Project VBA Automation”
Resume CleanUp
End Sub
‘—————————————————————-
‘ 補助関数: 安全なオブジェクト解放
‘—————————————————————-
Private Function ExitObject(ByRef targetObj As Object) As Object
On Error Resume Next
If Not targetObj Is Nothing Then
Set targetObj = Nothing
End If
Set ExitObject = Nothing
End Function
‘—————————————————————-
‘ 外部プロセス非同期呼び出し(Windows Script Host使用)
‘—————————————————————-
Private Sub InvokeAsyncGitCommit(ByVal repoDir As String, ByVal xmlFile As String, ByVal mppName As String)
Dim wshShell As Object
Dim commandLine As String
Set wshShell = CreateObject(“WScript.Shell”)
‘ バッチファイルまたは直接Gitコマンドを構築
‘ 非同期実行(第三引数をFalse、第4引数をTrueにすることでウィンドウを非表示にする)
‘ コミットメッセージには変更されたプロジェクト名を動的に挿入
commandLine = “cmd.exe /c cd /d “”” & repoDir & “”” && ” & _
“git add “”” & xmlFile & “”” && ” & _
“git commit -m “”Auto-commit: Update schedule for ” & mppName & ” [skip ci]”””
‘ Run(strCommand, intWindowStyle, bWaitOnReturn)
‘ intWindowStyle: 0 = ウィンドウ非表示 (SW_HIDE)
‘ bWaitOnReturn: False = 非同期実行(VBAをブロックしない)
wshShell.Run commandLine, 0, False
Set wshShell = ExitObject(wshShell)
End Sub
—
3. チーフアーキテクトが解説する実装の急所
A. なぜ `.mpp` ではなく `.xml` をGit管理するのか?
前述の通り、`.mpp`はバイナリであり、誰がどこを変更したのか(誰がどのタスクの工数を改ざんしたのか)の差分(Diff)が追えない。MS Projectがネイティブでサポートする `pjXML` 形式で出力することで、Gitの行単位の差分比較が可能になる。これにより、変更履歴の完全な監査証跡(Audit Trail)が確立される。
B. ウィンドウ非表示(`SW_HIDE`)と非同期(`False`)の徹底
バックグラウンドで `git` コマンドや `cmd.exe` がポップアップ表示されると、プロジェクトマネージャーやエンドユーザーは恐怖を覚える。
`WScript.Shell.Run` の第2引数に `0` を指定し、かつ第3引数を `False` にすることで、OSのプロセス空間上で完全にサイレントかつノンブロッキングに処理を完結させている。これにより、大規模なWBS(Work Breakdown Structure)を保存する際であっても、保存処理自体の体感速度が低下することはない。
C. COMオブジェクトのライフサイクル管理
VBAランタイムのガベージコレクションは極めて脆弱である。`CreateObject` で生成した `Scripting.FileSystemObject` や `WScript.Shell` をそのまま放置すると、VBA終了後もメモリ上にプロセスや参照が残り、ExcelやProjectの多重起動時やアドイン競合時にメモリリークを引き起こす。
本コードでは、独自に `ExitObject` 関数を定義し、エラーハンドリングの有無に関わらず確実な参照切断(`Set obj = Nothing`)を行う構造を徹底している。
—
4. 運用上の注意点とエンタープライズ要件
1. Gitの認証情報の事前構成:
リモートリポジトリ(GitHub, GitLab, Azure DevOpsなど)へプッシュ(Push)まで自動化する場合は、SSHキーのパスフレーズなし設定、またはGit Credential ManagerによるHTTPS認証のキャッシュが必須である。さもないと、見えないバックグラウンドプロセスでGitがパスワード入力を求めてハングアップする。
2. 大容量XMLの最適化:
プロジェクトがあまりにも巨大化すると、XMLファイルが数十MBに達し、Gitのリポジトリサイズを圧迫する。必要に応じて `.gitignore` の設定や、不要なリソースプールの除外を検討されたい。
総括
VBAはレガシーな言語と嘲笑されることもあるが、ホストアプリケーション(Microsoft Project)のイベントモデルと、OSのプロセス制御(Windows API / WSH)を正しく理解したエンジニアの手に掛かれば、近代的なCI/CDパイプラインの一部として完全に組み込むことができる。
コードの行数を減らすことではなく、「システムの堅牢性とユーザーのシームレスな体験の両立」。これこそが、プロフェッショナルなVBAアーキテクチャの極みである。
