【実務・中級編】【上級者向け】大規模プロジェクトの高速保存:不要なビューやキャッシュを最適化する – Project VBA解析バイブル

スポンサーリンク

【上級者向け】大規模プロジェクトの高速保存:不要なビューやキャッシュを最適化する

Microsoft Project(以下、MS Project)を用いた大規模な開発プロジェクトの管理において、誰もが一度は直面する致命的な問題があります。それは、「プロジェクトファイルの保存(Save)が異常に遅い」、そして「ファイルサイズ(.mpp)が日を追うごとに肥大化していく」という現象です。

数千タスク、数百リソースを抱えるエンタープライズ規模のプロジェクトでは、不用意な保存処理が数分単位のフリーズを引き起こし、自動化ツールの実行速度を著しく低下させます。

なぜ、ただの「保存」がこれほど重くなるのか?
その裏には、MS Project特有の描画キャッシュ、計算エンジンの挙動、そして内部バイナリの断片化(フラグメンテーション)という、一般的なOffice製品とは一線を画す特異なアーキテクチャが存在します。

本記事では、Project VBAを極限まで使いこなすアーキテクトの視点から、保存処理を劇的に高速化し、ファイルサイズを最小化するための「クリーンアップ&最適化保存」の極意を伝授します。

1. なぜ保存が遅くなるのか?ボトルネックの正体

MS Projectの保存処理(`FileSave`)がボトルネック化する要因は、主に以下の3点に集約されます。

① 一時的なカスタムビューやテーブルの「ゴミ」

自動化ツールやマクロが、処理の過程で一時的に作成したビュー、テーブル、フィルタ、グループ。これらは明示的に削除しない限り、プロジェクトファイル内にメタデータとして永続化されます。これらが蓄積されると、ファイルサイズが増加するだけでなく、ファイルオープン時や保存時のスキーマ検証に多大なオーバーヘッドが発生します。

② 重いビュー(描画キャッシュ)を開いたままの保存

複雑なガントチャートや、リソースグラフ、ネットワークダイアグラムを表示したまま保存を実行すると、MS Projectは「現在の表示状態(描画キャッシュやスクロール位置、展開/折りたたみ状態)」を忠実にシリアライズしてファイルに書き込もうとします。これが保存処理を極めて重くする隠れた要因です。

③ インクリメンタル保存(差分書き込み)による断片化

MS Projectは、通常の「上書き保存(Save)」を行う際、パフォーマンス向上のために内部データベースの差分のみを書き込む挙動(インクリメンタル保存)を選択することがあります。しかし、これを繰り返すと内部バイナリが断片化し、最終的にファイルサイズが肥大化し、読み込み・書き込み速度が共に低下します。

2. 高速・スリム化を実現する「堅牢なクリーンアップ・シーケンス」

これらの課題を解決するためには、保存処理を実行する直前に、VBAから以下の4ステップの最適化シーケンスを強制実行する必要があります。

[実行開始]


1. 計算エンジンを「手動(Manual)」に移行し、画面更新を抑止


2. 標準の最も軽量なビュー(例:「タスクシート」)へ強制切り替え
│(描画キャッシュの書き込みフットプリントを最小化)

3. 一時的に作成されたカスタムビュー/テーブルの完全パージ(削除)


4. 「名前を付けて保存(FileSaveAs)」によるバイナリの完全再構築(デフラグ)


[計算エンジンと画面更新を元に戻して終了]

特に重要なのは「タスクシート(Task Sheet)」への切り替えです。タスクシートはガントバーなどのグラフィック描画が一切ないため、MS Projectが保持すべき描画キャッシュがほぼゼロになります。この状態で保存するだけで、保存速度は劇的に向上します。

3. 極限の最適化保存を実現するプロダクションコード

以下に、実務の現場でそのまま利用できる、堅牢で保守性の高いVBA実装を示します。エラーハンドリング、ビルトインオブジェクトの保護、リソース解放を完璧に考慮したプロフェッショナル仕様です。

Option Explicit

”’

”’ 大規模プロジェクトファイルを最適化し、高速に保存するコアプロシージャ
”’

Public Sub OptimizeAndSaveProject()
Dim targetProject As MSProject.Project
Set targetProject = MSProject.ActiveProject

‘ プロジェクトが未オープン、または読み取り専用の場合は処理をスキップ
If targetProject Is Nothing Then Exit Sub
If targetProject.ReadOnly Then
MsgBox “プロジェクトファイルが読み取り専用のため、最適化保存を実行できません。”, vbExclamation, “処理中断”
Exit Sub
End If

‘ パフォーマンス向上のための画面更新抑止と計算モードの退避
Dim previousScreenUpdating As Boolean
Dim previousCalculation As Long

On Error GoTo ErrorHandler

‘ 現在の環境設定を退避し、最適化モードへ移行
previousScreenUpdating = MSProject.Application.ScreenUpdating
previousCalculation = MSProject.Application.Calculation

MSProject.Application.ScreenUpdating = False
MSProject.Application.Calculation = pjManual ‘ 計算エンジンを一時停止

‘———————————————————
‘ STEP 1: 最も軽量なビュー「タスクシート」への切り替え
‘———————————————————
‘ ガントチャート等の重い描画キャッシュを保存対象から外すための極めて重要な処理
Dim sLightView As String
sLightView = “Task Sheet” ‘ 英語版/日本語版双方に対応するため、環境に応じて調整

On Error Resume Next
MSProject.ViewApply Name:=sLightView
If Err.Number <> 0 Then
‘ 日本語環境用のフォールバック
MSProject.ViewApply Name:=”タスク シート”
Err.Clear
End If
On Error GoTo ErrorHandler

‘———————————————————
‘ STEP 2: 一時ビューおよび一時テーブルのパージ(クリーンアップ)
‘———————————————————
‘ 例として、ツールが一時的に作成した “Tmp_” で始まるオブジェクトを削除
Call PurgeTemporaryObjects(targetProject)

‘———————————————————
‘ STEP 3: 計算の強制再計算(データの整合性を保証)
‘———————————————————
‘ 手動計算のまま保存すると、次回オープン時に不整合が生じるリスクがあるため、
‘ 保存直前に1度だけフル再計算を実行する
MSProject.CalculateAll

‘———————————————————
‘ STEP 4: バイナリ再構築(デフラグ保存)の実行
‘———————————————————
‘ 単なる FileSave ではなく、同一パスに対して FileSaveAs を実行することで、
‘ MS Project内部のデータベースを完全に再構築(デフラグ)し、ファイルサイズを極限まで縮小する。
Dim filePath As String
filePath = targetProject.FullName

‘ 新規ファイル(未保存)の場合は保存ダイアログを表示
If InStr(filePath, “\”) = 0 Then
MSProject.Application.FileSave
Else
‘ 同名で「名前を付けて保存」を実行(上書き警告を抑止して実行)
MSProject.Application.Alerts False
MSProject.FileSaveAs _
Name:=filePath, _
FormatID:=”MSProject.MPP”
MSProject.Application.Alerts True
End If

MsgBox “プロジェクトファイルの最適化保存が完了しました。”, vbInformation, “成功”

CleanUp:
‘ 環境設定の復元(必ず実行されるように保証する)
MSProject.Application.ScreenUpdating = previousScreenUpdating
MSProject.Application.Calculation = previousCalculation
Exit Sub

ErrorHandler:
MSProject.Application.Alerts True
MsgBox “最適化保存中に予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー発生”
Resume CleanUp
End Sub

”’

”’ “Tmp_” プレフィックスを持つ一時的なビューとテーブルを安全に削除する
”’

Private Sub PurgeTemporaryObjects(ByRef targetProject As MSProject.Project)
On Error Resume Next ‘ 削除失敗時のエラーを無視してループを継続

‘ 1. ビューのクリーンアップ
Dim viewName As Variant
Dim i As Long

‘ Viewsコレクションを逆順でループ(削除によるインデックスずれ防止)
For i = targetProject.Views.Count To 1 Step -1
viewName = targetProject.Views.Item(i).Name
‘ プレフィックス “Tmp_” で始まるビュー、かつ現在適用されていないビューを削除
If Left(viewName, 4) = “Tmp_” Then
‘ 現在アクティブなビューは削除できないため安全弁をかける
If viewName <> targetProject.CurrentView Then
targetProject.Views.Item(i).Delete
End If
End If
Next i

‘ 2. テーブルのクリーンアップ
Dim tableName As String
For i = targetProject.TaskTables.Count To 1 Step -1
tableName = targetProject.TaskTables.Item(i).Name
If Left(tableName, 4) = “Tmp_” Then
targetProject.TaskTables.Item(i).Delete
End If
Next i

On Error GoTo 0
End Sub

4. プロフェッショナルが紐解くコードの急所

このコードがなぜ大規模プロジェクトにおいて劇的な効果をもたらすのか、そのアーキテクチャ上の理由を解説します。

① `Task Sheet` への切り替えがもたらす「描画レス」の効果

MS Projectのファイル保存時、最もリソースを消費するのは「ガントチャートのタイムスケール」や「進捗線の描画状態」といったビュー固有の非構造化キャッシュデータです。
保存前にこれらを排除した「タスクシート(ただのグリッド)」に切り替えることで、シリアライズ対象のデータ量が激減し、保存処理のCPU・メモリ負荷を最小限に抑えることができます。

② `FileSaveAs` による「物理デフラグ」

コード内で、すでにパスが存在するファイルに対してもあえて `FileSaveAs` を実行しています。
MS Projectにおいて、`FileSave`(上書き保存)は「追記型」に近い挙動をとることがあり、内部データベースにゴミデータが残存します。一方、`FileSaveAs` を同一名で実行すると、スキーマの再構築とデータのクリーンコピー(物理デフラグ)が強制されるため、ファイルサイズが数十%削減されるケースも珍しくありません。

③ 自動計算(`Calculation`)の適切な制御

大規模プロジェクトでは、タスクが1つ動くだけで、数千のタスクのクリティカルパスが再計算されます。
保存処理の前後に `MSProject.Application.Calculation = pjManual` を挟み、最後に `CalculateAll` を1度だけ呼び出すことで、ビュー切り替えやオブジェクト削除のたびに発生する無駄なバックグラウンド計算を完全にシャットアウトしています。

5. 現場での運用・設計上の注意点

この最適化コードを実務の共通モジュールに組み込むにあたり、以下の設計思想を念頭に置いてください。

1. ビルトインオブジェクトの保護
一時オブジェクトを削除する際、プレフィックス(例: `Tmp_`)を厳格に管理してください。MS Projectに標準で組み込まれている「Gantt Chart」や「Entry」テーブルなどを誤って削除しようとすると、システムエラーを引き起こします。
2. 共有ファイル(SharePoint / Project Server)環境での挙動
ローカルの `.mpp` ファイルではなく、Project Server や Project Online(Enterprise Project)環境下でこの処理を行う場合、`FileSaveAs` の挙動が異なります。サーバー環境では、チェックアウト・チェックインのステータス管理が優先されるため、ローカル保存とサーバー同期のライフサイクルを考慮したラッパー関数を構築してください。

まとめ:アーキテクチャを理解したコードが、真の効率化を生む

Office VBAの中でも、MS Projectのオブジェクトモデルは特に「重厚」であり、メモリ管理や描画キャッシュの制御がパフォーマンスに直結します。

今回紹介した「ビューの最軽量化」「一時オブジェクトのパージ」「FileSaveAsによるデフラグ」というアプローチは、大規模プロジェクトを扱うプロフェッショナルにとって必須の最適化技術です。

ただ動くだけのコードから、数万行のタスクを高速に制御できる洗練されたシステムへ。この極限の知見を、ぜひあなたのプロジェクト自動化ツールに実装し、圧倒的なパフォーマンスを体感してください。

タイトルとURLをコピーしました