【上級者向け】MS Projectのグローバルテンプレート(.MPT)を動的に切り替える極限の設計術
開発現場でMicrosoft Project(以下、MSP)をエンタープライズ規模で運用していると、必ず直面する壁がある。それが「グローバルテンプレート(`Global.mpt`)」の管理矛盾だ。
カスタムフィールド、独自のビュー、テーブル、そしてVBAマクロ。これらを全社あるいはプロジェクト種別ごとに統一しようと、ローカルの `Global.mpt` を上書き配布する運用をしていなだろうか?
今すぐその非効率なやり方を捨てなさい。 ファイルの直接上書きは、ユーザーの環境依存バグ、勝手なローカルカスタマイズによる競合、そしてバージョン不整合によるファイル破損(Corruption)の温床でしかない。
真にスケーラブルなMSP自動化アーキテクトは、コードベースで動的に読み込むテンプレート(.mpt)のパスを制御し、プロジェクトの性質に応じた「実行環境の仮想化」を行う。
今回は、VBAを用いてプロジェクト起動時や新規作成時に `Global.mpt` を動的に切り替え、環境依存のトラブルを完全にハックする堅牢な設計手法を伝授する。
—
1. なぜ「静的なGlobal.mpt置き換え」は破綻するのか?
MSPの仕様上、アプリケーションが起動する際に読み込まれるのは、原則としてローカルPCのユーザープロファイル内に存在する `Global.mpt` である。
C:\Users\<ユーザー名>\AppData\Roaming\Microsoft\MS Project\15\JA-JP\Global.mpt
ここに手を加えるアプローチがなぜ現場を崩壊させるのか。理由は3つある。
1. 排他制御の失敗: MSPが起動している状態でファイルを上書きしようとすると、アクセス権エラー(Permission Denied)が発生する。
2. クラウド・リモートワーク環境の限界: SharePointやOneDrive上に置いたテンプレートを同期ズレのまま読み込み、グローバルデータがコンフリクトを起こす。
3. プロジェクト特性の無視: 「アジャイル型開発用」と「大規模ウォーターフォール型(EVM必須)用」では、必要なカスタムフィールドの定義やテーブル構成が全く異なる。それらを1つのGlobal.mptに同居させるのは設計の敗北だ。
解決アプローチ:動的Mptローダーの構築
MSPには、コマンドライン引数や、COMオブジェクトとしてのインスタンス生成時にテンプレートを指定するフックが存在する。これをVBA、あるいは外部VBS/PowerShellランチャーから制御し、「プロジェクトファイル生成の瞬間」に適切な.mptをバインドする。
—
2. 堅牢な設計:動的テンプレート切り替えアーキテクト
今回は、すでに開いているMSPセッション内において、特定のプロジェクト要件(例:種別A:ITインフラ構築、種別B:ソフトウェア開発)に応じて、参照すべきベーステンプレートからビューやモジュールを動的にインポート・適用する、あるいはインスタンス起動時にテンプレートを強制するプロダクションコードを提示する。
実務でそのまま組み込めるよう、エラーハンドリングとオブジェクトのライフサイクルを完全に考慮した実装を行っている。
プロダクションコード例
以下のコードは、MSPのアドインあるいはマクロファイル(.bas)に実装し、プロジェクトの初期化フェーズで呼び出すことを想定している。
Option Explicit
‘ ==============================================================================
‘ モジュール名: MptDynamicSwitcher
‘ 概要 : プロジェクトの特性に応じてグローバルテンプレートを動的に切り替える
‘ 著者 : 首席アーキテクト
‘ ==============================================================================
Private Const TEMPLATE_DIR As String = “C:\EnterpriseMSP\Templates\”
Private Const TYPE_INFRA As String = “INFRA”
Private Const TYPE_SW As String = “SOFTWARE”
Public Sub InitializeProjectWithDynamicMpt(ByVal projectType As String)
Dim targetMptPath As String
Dim activeProj As Project
‘ 1. 実行時エラーハンドリングの準備
On Error GoTo ErrorHandler
‘ 2. プロジェクト種別に応じたテンプレートパスの解決
targetMptPath = ResolveTemplatePath(projectType)
If targetMptPath = “” Then
Err.Raise vbObjectError + 1000, “MptSwitcher”, “指定されたプロジェクト種別に対するテンプレートが見つかりません: ” & projectType
End If
‘ アクティブプロジェクトの存在確認
If ActiveProject Is Nothing Then
‘ プロジェクトが存在しない場合は新規作成
FileNew Template:=targetMptPath
Else
Set activeProj = ActiveProject
‘ 既存プロジェクトに対してカスタム要素(Organizer)を動的に同期・インポート
Call SyncCustomElements(targetMptPath, activeProj)
End If
MsgBox “テンプレートの動的適用が正常に完了しました。”, vbInformation, “環境適応型MSP”
Exit Sub
ErrorHandler:
MsgBox “【致命的なエラー】テンプレートの切り替えに失敗しました。” & vbCrLf & _
“Error 0x” & Hex(Err.Number) & “: ” & Err.Description, vbCritical, “システムエラー”
‘ ログ出力や異常終了処理をここに記述
End Sub
Private Function ResolveTemplatePath(ByVal pType As String) As String
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim path As String
Select Case UCase(Trim(pType))
Case TYPE_INFRA
path = TEMPLATE_DIR & “Infra_Standard_Global.mpt”
Case TYPE_SW
path = TEMPLATE_DIR & “Software_Agile_Global.mpt”
Case Else
path = TEMPLATE_DIR & “Default_Global.mpt”
End Select
‘ ファイルが存在するか厳密にチェック
If fso.FileExists(path) Then
ResolveTemplatePath = path
Else
ResolveTemplatePath = “”
End If
Set fso = Nothing
End Function
Private Sub SyncCustomElements(ByVal mptPath As String, ByRef prj As Project)
‘ Organizerオブジェクトを使用して、テンプレートから最新のビュー、テーブル、
‘ フィールド定義を現在のプロジェクトに安全にインポートする
On Error GoTo OrganizerError
‘ 例:カスタムテーブルのインポート(必要に応じてViews, Modules等も拡張可能)
OrganizerCopy Source:=mptPath, _
Destination:=prj.FullName, _
Name:=”リソース配分テーブル”, _
Object:=pjTable
Exit Sub
OrganizerError:
‘ 競合やすでに存在する場合のエラーはスルーまたはログ記録
Debug.Print “Organizer Warning: ” & Err.Description
Resume Next
End Sub
—
3. データベース連携とネットワークパスの罠
上記のような動的切り替えを組織展開する際、必ずエンジニアがハマる「実務の罠」がある。
1. ネットワーク遅延(UNCパス)によるタイムアウト
`TEMPLATE_DIR` に `\\server\share\templates\` のようなネットワークパス(UNCパス)を指定した場合、VPN接続時や社内LANのトラフィック状況によって `FileExists` 判定が遅延、あるいはフリーズを引き起こす。
- 対策:
起動時にローカルキャッシュディレクトリ(例: `%LOCALAPPDATA%\EnterpriseMSP\Cache`)へサーバーからマスターMPTをハッシュ値付きで同期(ミラーリング)し、コードからは常にローカルのキャッシュパスを参照させる設計にすること。
2. OrganizerCopyの落とし穴
`OrganizerCopy` メソッドは非常に強力だが、同名のカスタムフィールドやテーブルが既に存在する場合、サイレントエラーになるか、予期せぬ上書きが発生する。
プロダクションコードでは、インポート前に既存のコレクションを走査(あるいはエラーCatcherを厳密に配置)し、バージョン管理されたUIDベースで差分適用するロジックを組むのがプロの作法だ。
—
4. チーフアーキテクトからの提言
ツールやマクロの散逸を防ぎ、組織全体の生産性を底上げしたいのであれば、「どこでも動く属人化したマクロ」を作るな。
今回解説したように、「環境やプロジェクト要件をコード側が検知し、必要なリソース(MPTやテンプレート)を動的にアセンブルする」という設計思想こそが、大規模MSP運用における唯一の正解である。
手動でのファイル置き換え作業は今すぐ廃止し、コードによる動的管理へ移行せよ。あなたの書くVBAが、組織のプロジェクトマネジメントの信頼性を担保する基盤となるのだ。
