Project VBAを掌握する極限の知見:肥大化したMSPファイルを救う「カスタムビュー・フィルタ」一括パージ最適化
プロジェクト管理の現場において、Microsoft Project(MSP)の `.mpp` ファイルが数年間にわたる運用によって肥大化していく現象は、多くのシニアエンジニアやインフラ管理者を悩ませる悪夢の一つだ。
特に、複数部門が入り乱れるの大規模プロジェクトでは、現場の担当者が勝手に作成した無数のカスタムビュー、一時的なフィルタ、不要なグループ定義がファイル内に蓄積し、I/Oのボトルネックやメモリリーク、最悪の場合はファイル破損の温床となる。
今回は、Project VBAのオブジェクトモデルの深層に踏み込み、プロジェクト保存のフックを利用して「不要なカスタムビューとフィルタをプログラム的に一括削除(パージ)し、極限までファイルを軽量化・最適化するアーキテクチャ」を解説する。
—
1. 肥大化の元凶:MSPのコレクション構造とメモリの闇
MS ProjectのファイルフォーマットおよびVBAオブジェクトモデルは、ExcelやWordに比べて特異なライフサイクルを持っている。
ユーザーがGUI上で作成したカスタムビュー(`Views` コレクション)やフィルタ(`Filters` コレクション)は、プロジェクトファイル自体のメタデータとしてシリアライズされる。これらはタスクやリソースのデータ本体ではないため軽視されがちだが、数千レベルのゴミデータが蓄積すると、以下の問題を引き起こす。
- COMオブジェクトの肥大化とシリアライズ時間の増大: 保存時に不要なXML/バイナリノードの書き出しが発生し、I/O性能が著しく低下する。
- グローバルテンプレート(Global.mpt)との衝突: ローカルファイルに埋め込まれたカスタムビューがグローバル側と競合し、予期せぬUIのフリーズや例外を引き起こす。
我々エンジニアは、ガベージコレクションや手動のクリーンアップに頼るのではなく、「保存時イベント(BeforeSave)をトリガーとした自動パージ機構」をコードベースで常時稼働させるべきである。
—
2. アーキテクチャ設計:安全かつ高速なパージ処理の要件
不要なビューやフィルタを削除するにあたり、以下の致命的な罠が存在する。
1. ビルトイン(標準)オブジェクトの削除禁止: MSPの標準ビュー(ガントチャートなど)や標準フィルタを誤って削除すると、アプリケーションがクラッシュするか、次回のオープン時に整合性エラーが発生する。
2. アクティブビューの安全確保: 現在ユーザーが表示しているビューを削除対象にしてしまうと、ポインタが無効化され、VBAランタイムエラー(エラー番号:1101等)が即座に発生する。
これらを回避するため、削除ロジックには厳密な「保護フィルター」をかけ、さらにオブジェクトの解放を明示的に行う必要がある。
—
3. 実装コード:極限まで最適化されたパージ・モジュール
以下のコードは、`ThisProject` クラスモジュール、または標準モジュールに実装し、プロジェクトの保存イベント(または手動実行)から呼び出すことを想定した実用コードである。
Option Explicit
‘ ==============================================================================
‘ módulo名: modProjectOptimizer
‘ 概要: 肥大化したプロジェクトファイルから不要なカスタムビューとフィルタを
‘ 安全に一括パージし、ファイルサイズとメモリを最適化する
‘ ==============================================================================
Public Sub PurgeUnusedCustomObjects()
Dim appMSProject As MSProject.Application
Set appMSProject = ActiveProject.Application
‘ 画面描画とアラートを完全に抑制し、実行速度を極限まで引き上げる
appMSProject.ScreenUpdating = False
appMSProject.DisplayAlerts = False
On Error GoTo ErrorHandler
‘ 1. カスタムフィルタのパージ処理
Call PurgeFilters(ActiveProject)
‘ 2. カスタムビューのパージ処理
Call PurgeViews(ActiveProject)
‘ ガベージコレクション的なメモリ解放を促すため、強制的にオブジェクト変数をクリア
MsgBox “プロジェクトの最適化(ビュー・フィルタのパージ)が完了しました。”, vbInformation, “最適化完了”
CleanUp:
appMSProject.DisplayAlerts = True
appMSProject.ScreenUpdating = True
Set appMSProject = Nothing
Exit Sub
ErrorHandler:
MsgBox “最適化処理中に致命的なエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
‘ ——————————————————————————
‘ フィルタのパージ(ビルトインを除外して安全に削除)
‘ ——————————————————————————
Private Sub PurgeFilters(ByRef prj As Project)
Dim flt As Filter
Int i As Long
‘ コレクションを逆順でループ(削除時のインデックスズレを防ぐための鉄則)
For i = prj.Filters.Count To 1 Step -1
Set flt = prj.Filters(i)
‘ 判定ロジック:
‘ 1. ユーザー定義(Custom)であること
‘ 2. 標準(BuiltIn)ではないこと
On Error Resume Next
If Not flt.BuiltIn Then
‘ 依存関係や参照エラーを回避するため、エラーを無視しつつ削除を実行
flt.Delete
End If
On Error GoTo 0
Set flt = Nothing
Next i
End Sub
‘ ——————————————————————————
‘ ビューのパージ(アクティブビューとの衝突を回避)
‘ ——————————————————————————
Private Sub PurgeViews(ByRef prj As Project)
Dim vw As View
Dim activeViewName As String
Dim i As Long
‘ 現在アクティブなビューの名称を退避(これを削除すると破綻するため)
On Error Resume Next
activeViewName = ActiveWindow.View.Name
On Error GoTo 0
For i = prj.Views.Count To 1 Step -1
Set vw = prj.Views(i)
On Error Resume Next
‘ ビルトインではなく、かつ現在アクティブ表示されていないビューのみ削除対象とする
If Not vw.BuiltIn Then
If vw.Name <> activeViewName Then
vw.Delete
End If
End If
On Error GoTo 0
Set vw = Nothing
Next i
End Sub
—
4. シニアエンジニアのための高度な解説:実装の急所
上記のコードには、レガシー環境や大規模システム連携を見据えたアーキテクチャ上の重要なノウハウが凝縮されている。
① コレクションの逆順ループ (`Step -1`)
VBAにおけるコレクション要素の削除において、先頭から順に (`1 To Count`) 削除を行うと、インデックスの詰め直しが発生して要素のスキップや予期せぬ実行時エラーを引き起こす。「コレクション操作は常に末尾から逆順で行う」という鉄則をここでも厳守している。
② アクティブオブジェクトの保護
`ActiveWindow.View.Name` を事前に取得し、現在画面に描画されているビューの削除を物理的にブロックしている。もしこれを怠ると、MSPのCOMインターフェースが内部ポインタの喪失によりハングアップを引き起こす。
③ 画面描画の抑制 (`ScreenUpdating = False`)
数千件のオブジェクトを走査・削除する際、GUIの再描画が走るとパフォーマンスが数分の1に低下する。APIレベルでの描画抑制により、処理をミリ秒単位で完了させることが可能となる。
—
5. 自動化の極み:BeforeSaveイベントとのフック
手動でこのマクロを走査させるのではなく、プロジェクトが保存される直前に自動実行させることで、ユーザーに意識させずにファイルサイズを常にクリーンに保つことができる。
ThisProjectクラスモジュールに以下のイベントハンドラを記述する。
Private Sub Project_BeforeSave(ByVal AS_Project As Project)
‘ 保存処理が走るたびに自動で不要ビュー・フィルタをパージ
‘ ※大規模プロジェクトで保存頻度が高い場合は、タイムスタンプによる実行制御を入れるとさらに堅牢になります。
Call PurgeUnusedCustomObjects
End Sub
—
総括
Project VBAにおけるリソース管理は、単なる「コードの記述」にとどまらず、アプリケーションのメモリライフサイクルとCOMコンポーネントの挙動を完全に理解していることが求められる。
今回紹介したカスタムビュー・フィルタのパージ処理を導入することで、肥大化したレガシープロジェクトファイルの軽量化だけでなく、ネットワークトラフィックの削減やシステム間連携(REST APIやDBへのエクスポート)の安定性向上にも直結する。
プロフェッショナルとして、システムの内側から常にコードとデータを美しく保つこと。それこそが、真の業務自動化エンジニアの流儀である。
