【入門編】【上級者向け】プロジェクトの保存時に、不要なカスタムビュー・フィルタ・グループを一括削除してファイルを極限まで軽量化する最適化 – Project VBA解析バイブル

スポンサーリンク

皆さん、こんにちは!チーフアーキテクトの〇〇です。

業務自動化の世界へようこそ!特にMicrosoft Project VBAは、その奥深さとパワフルさで、あなたのプロジェクト管理を劇的に変える可能性を秘めています。

「Projectのファイル、なんだか最近重いな…」
「マクロを記録してみたけど、これって本当に効率的なのかな?」

そう感じているあなたに、今日は「Project VBAを掌握する極限の知見」を、魂を込めてお伝えします。一般的なリファレンスの引き写しのような退屈な記事は書きません。オブジェクトのライフサイクルやパフォーマンスの重みを知り尽くした者だけが語れる、本質的な知識を、優しく、そして深く掘り下げていきましょう。

今日のテーマは、プロジェクトファイルの「ダイエット」です。まるで使われていない資料が積み重なった巨大な倉庫のように肥大化しがちなProjectファイルを、スマートに、そしてサクサク動く状態に保つための秘伝のテクニックをお教えします。

なぜProjectファイルは「太る」のか?その深刻な影響とは

プロジェクトファイルを扱っていると、徐々にファイルサイズが大きくなったり、開くのに時間がかかったり、操作がもっさりしたりする経験はありませんか?これは、ファイル内に「不要な情報」が蓄積されているサインかもしれません。

Projectファイル肥大化のメカニズム

Microsoft Projectは、プロジェクトに関するあらゆる情報を一つのファイルに詰め込みます。タスク、リソース、割り当てといった主要なデータはもちろんのこと、以下のような「定義」も、あなたが意識しないうちにどんどん蓄積されていきます。

  • カスタムビュー: 特定の目的のために作成した表示設定(例: 「私のタスク進捗ビュー」「コスト分析ビュー」)
  • カスタムフィルタ: 特定の条件でタスクを絞り込むための設定(例: 「未完了タスクのみ」「担当者Aのタスク」)
  • カスタムグループ: タスクを特定の基準で分類・集計するための設定(例: 「フェーズ別」「優先度別」)

これらは、プロジェクト管理を効率化するための便利なツールですが、一度作成すると、使わなくなってもファイル内に残り続けます。特に、試行錯誤の過程で「とりあえず作ってみた」ビューやフィルタが、いつの間にか大量に蓄積されている、なんてことは珍しくありません。

肥大化が引き起こす問題

ファイルが肥大化すると、以下のような深刻な問題を引き起こします。

1. パフォーマンスの低下: ファイルのオープン・保存に時間がかかり、操作中の反応が鈍くなります。
2. 共有性の悪化: 大容量のファイルはメール添付が困難になり、ネットワーク経由での共有も時間がかかります。
3. 安定性の低下: 不安定なデータ構造は、予期せぬエラーやクラッシュの原因となることがあります。
4. バックアップの負担: バックアップにかかる時間やストレージ容量が増大します。

これらの問題を未然に防ぎ、プロジェクトを常に最適な状態で運用するためには、定期的な「クリーンアップ」が不可欠です。しかし、手作業で一つずつ確認して削除するのは大変な手間ですよね?そこでProject VBAの出番です!

【本質理解】Projectオブジェクトモデルの核心に迫る

Project VBAを扱う上で最も重要なのは、「Projectが何をどのように管理しているか」というオブジェクトモデルを理解することです。ここをクリアすれば、Project VBAの基本はバッチリですよ!

`ActiveProject` オブジェクトとは?

今、あなたがProjectで開いているファイルそのものが、VBAの世界では`ActiveProject`というオブジェクトとして表現されます。私たちは、この`ActiveProject`を起点にして、ファイル内の様々な情報にアクセスしたり、操作したりします。

コレクションとアイテム:情報の「入れ物」と「中身」

Projectのオブジェクトモデルは、非常に整理された構造をしています。特に重要なのが「コレクション」と「アイテム」の関係です。

  • コレクション (Collection): 特定の種類のオブジェクトを複数格納する「入れ物」です。例えば、プロジェクト内の全てのビューは`Views`コレクションの中に、全てのフィルタは`Filters`コレクションの中にまとめられています。
  • アイテム (Item): コレクションの中に格納されている個々のオブジェクトです。例えば、`Views`コレクションの中には、個々の`View`オブジェクト(「ガントチャート」「タスクシート」など)がアイテムとして存在します。

私たちが今回ターゲットにするのは、以下のコレクションです。

  • `ActiveProject.Views`:プロジェクト内の全てのビュー(表示設定)のコレクション
  • `ActiveProject.Filters`:プロジェクト内の全てのフィルタ(絞り込み設定)のコレクション
  • `ActiveProject.Groups`:プロジェクト内の全てのグループ(集計設定)のコレクション

これらのコレクションの中を一つずつ見て回り、不要な「アイテム」を削除していく、というのが今回のクリーンアップの基本戦略になります。

実装の準備:VBAエディタの開き方

まずはProject VBAを記述するための環境を準備しましょう。

1. Projectを開く: 軽量化したいプロジェクトファイルを開いてください。
2. VBAエディタを開く:

  • リボンメニューの「開発」タブをクリックします。
  • 「コード」グループにある「Visual Basic」をクリックします。
  • (「開発」タブが表示されていない場合:「ファイル」→「オプション」→「リボンのユーザー設定」で「開発」にチェックを入れてください。)

3. 標準モジュールの挿入:

  • VBAエディタの左側にある「プロジェクトエクスプローラ」で、対象のプロジェクト(`VBAProject(プロジェクトファイル名)`)を右クリックします。
  • 「挿入」→「標準モジュール」を選択します。
  • すると、右側の大きな空白の領域に新しいモジュール(`Module1`など)が作成され、コードを記述できるようになります。

メインスクリプト:不要な定義を一括削除してファイルを極限まで軽量化!

さあ、いよいよ本丸のコードです。今回は、カスタムビュー、カスタムフィルタ、カスタムグループを一括で削除するマクロを作成します。

最適化の核となる考え方

「使われていない定義」とは、言い換えれば「ユーザーが独自に作成した定義」です。Projectには最初から「ガントチャート」「すべてのタスク」のような組み込みの(`BuiltIn`)定義があります。これらは削除してはいけませんし、できません。私たちが削除すべきは、`BuiltIn`ではない、つまりユーザーが追加した定義だけです。

この判断には、各オブジェクトが持つ`BuiltIn`プロパティが非常に役立ちます。このプロパティが`False`であれば、それはカスタム定義であると判断できるのです。

VBAコード例

以下のコードを、先ほど開いた標準モジュールに貼り付けてください。

Option Explicit ‘ 変数の宣言を強制し、バグを未然に防ぎます。優秀なエンジニアの必須設定です。

‘// プロジェクトファイルの軽量化マクロ – 不要なカスタム定義を一掃 //
‘// このマクロは、現在のプロジェクトからユーザーが作成したカスタムビュー、フィルタ、グループを削除し、
‘// ファイルサイズを最適化します。組み込みの定義は削除しません。

Sub OptimizeProjectFile()

‘————————————————————————–
‘ パフォーマンスとユーザー体験の向上:初期設定
‘————————————————————————–
‘ 画面更新を一時的に停止します。これにより、処理中の画面のちらつきがなくなり、
‘ マクロの実行速度が大幅に向上します。描画処理はCPUに負荷がかかるため、停止は非常に効果的です。
Application.ScreenUpdating = False

‘ エラーが発生した場合の処理を設定します。
‘ 予期せぬ問題でマクロが停止しないよう、堅牢なコードには必須の要素です。
On Error GoTo ErrorHandler

‘————————————————————————–
‘ オブジェクト変数の宣言と取得
‘————————————————————————–
Dim prj As Project ‘ Projectオブジェクトを格納する変数
Set prj = ActiveProject ‘ 現在開いているプロジェクトファイルを取得し、変数にセットします。
‘ これが、私たちが操作するプロジェクトの「入り口」となります。

Dim obj As Object ‘ 各コレクションのアイテム(View, Filter, Group)を一時的に格納する汎用オブジェクト変数。
‘ 型をObjectにすることで、様々な種類のアイテムに対応できます。

‘————————————————————————–
‘ 1. カスタムビューの削除
‘————————————————————————–
Debug.Print “カスタムビューのクリーンアップを開始します…” ‘ イミディエイトウィンドウに進行状況を表示します。
For Each obj In prj.Views ‘ プロジェクト内の全てのViewオブジェクトを一つずつループします。
‘ BuiltInプロパティがFalseの場合、それはユーザーが作成したカスタムビューです。
If Not obj.BuiltIn Then
Debug.Print ” – ビューを削除: ” & obj.Name ‘ 削除するビューの名前を表示します。
obj.Delete ‘ 該当するビューを削除します。
End If
Next obj ‘ 次のビューへ
Debug.Print “カスタムビューのクリーンアップが完了しました。”

‘————————————————————————–
‘ 2. カスタムフィルタの削除
‘————————————————————————–
Debug.Print “カスタムフィルタのクリーンアップを開始します…”
For Each obj In prj.Filters ‘ プロジェクト内の全てのFilterオブジェクトを一つずつループします。
‘ BuiltInプロパティがFalseの場合、それはユーザーが作成したカスタムフィルタです。
If Not obj.BuiltIn Then
Debug.Print ” – フィルタを削除: ” & obj.Name
obj.Delete ‘ 該当するフィルタを削除します。
End If
Next obj
Debug.Print “カスタムフィルタのクリーンアップが完了しました。”

‘————————————————————————–
‘ 3. カスタムグループの削除
‘————————————————————————–
Debug.Print “カスタムグループのクリーンアップを開始します…”
For Each obj In prj.Groups ‘ プロジェクト内の全てのGroupオブジェクトを一つずつループします。
‘ BuiltInプロパティがFalseの場合、それはユーザーが作成したカスタムグループです。
If Not obj.BuiltIn Then
Debug.Print ” – グループを削除: ” & obj.Name
obj.Delete ‘ 該当するグループを削除します。
End If
Next obj
Debug.Print “カスタムグループのクリーンアップが完了しました。”

‘————————————————————————–
‘ 4. ベースラインのクリア (オプション、極めて慎重に)
‘————————————————————————–
‘ ベースラインはプロジェクトの進捗管理において非常に重要な要素です。
‘ 安易な削除はデータの整合性を損なう可能性があります。
‘ ここでは例として提示しますが、通常は残しておくべきです。
‘ 極限の軽量化が必要な場合や、テストファイルでのみ検討してください。

‘ prj.BaselineClear All:=True ‘ !!! 警告: 全てのベースラインをクリアします。非常に強力な操作です !!!
‘ prj.BaselineClear BaselineType:=pjBaselineDelta ‘ 特定のベースライン型(例: デルタベースライン)をクリア

‘————————————————————————–
‘ 5. プロジェクトの保存 (変更を永続化)
‘————————————————————————–
‘ 削除した変更をプロジェクトファイルに実際に保存します。
‘ この処理がないと、行った削除は一時的なものとなり、ファイルを開き直すと元に戻ってしまいます。
If prj.Saved = False Then ‘ プロジェクトが変更されている場合のみ保存を実行します。
prj.Save ‘ プロジェクトを保存します。
Debug.Print “プロジェクトが保存されました。”
Else
Debug.Print “プロジェクトに変更はありませんでした。(または既に保存されています)”
End If

‘————————————————————————–
‘ 処理完了メッセージ
‘————————————————————————–
MsgBox “プロジェクトファイルの最適化が完了しました!ファイルがスマートになりましたね。”, vbInformation

Exit Sub ‘ 正常終了した場合、エラーハンドラへのジャンプをスキップします。

‘————————————————————————–
‘ エラーハンドラ:問題発生時の対応
‘————————————————————————–
ErrorHandler:
‘ エラーメッセージをユーザーに分かりやすく表示します。
MsgBox “プロジェクトファイルの最適化中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description & vbCrLf & _
“もしよろしければ、この情報を開発者に連絡してください。”, vbCritical, “エラー発生”

Finally:
‘————————————————————————–
‘ クリーンアップ:処理の終わりに必ず実行される部分
‘————————————————————————–
‘ 画面更新を再開します。これを忘れると、Projectの画面が更新されなくなってしまいます。
Application.ScreenUpdating = True
‘ オブジェクト変数を解放します。
‘ これを怠ると、メモリ上に不要な参照が残り続け、メモリリークの原因となる可能性があります。
‘ 常にSet obj = Nothingを心がけましょう。
Set prj = Nothing
Set obj = Nothing

End Sub

コードの実行方法

1. VBAエディタで上記のコードを貼り付けたモジュールが表示されていることを確認します。
2. `Sub OptimizeProjectFile()` の行の中にカーソルを置きます。
3. VBAエディタのツールバーにある「実行」(緑色の三角のアイコン)をクリックするか、F5キーを押します。

マクロが実行され、完了メッセージが表示されたら、プロジェクトファイルはクリーンアップされています!

さらに一歩踏み込む:オブジェクトのライフサイクルとパフォーマンスの極意

単にコードを動かすだけでなく、その裏にあるProjectの動作原理やパフォーマンスへの影響を理解することで、あなたは「伝説のチーフアーキテクト」への道を一歩踏み出せます。

`Option Explicit` の勧め

コードの冒頭にある`Option Explicit`は、変数の宣言を強制するVBAの文法です。これを記述することで、typoによる変数名の間違いなどの初歩的なバグを未然に防ぎ、コードの可読性と堅牢性を大幅に向上させます。開発の現場では、ほぼ100%のケースで`Option Explicit`を記述します。

`Application.ScreenUpdating = False` の効果

これは、まさにパフォーマンスチューニングの金字塔です。Project(ExcelやWordでも同様ですが)は、VBAでオブジェクトを操作するたびに、その変更を画面に反映しようとします。この「画面描画」は非常にコストの高い処理であり、マクロの実行速度を著しく低下させます。

`Application.ScreenUpdating = False`とすることで、マクロの実行中は画面描画を停止させ、処理が完了した後に一気に結果を反映させることができます。これにより、見た目のちらつきもなくなり、ユーザー体験も向上します。忘れずに`True`に戻すのを`Finally`ブロックで保証しましょう。

`Debug.Print` の活用

`Debug.Print`は、開発中にイミディエイトウィンドウ(VBAエディタの「表示」メニューから開けます)にメッセージを出力するための非常に便利な機能です。マクロがどの段階を実行しているか、どのようなデータを処理しているかを確認する際に役立ちます。本番環境では削除しても構いませんが、開発中は積極的に活用しましょう。

`Set obj = Nothing` の重要性:メモリリーク防止

VBAにおけるオブジェクト変数は、メモリ上に確保されたオブジェクトへの「参照」を保持しています。マクロの実行が終了しても、この参照が適切に解放されないと、メモリ上に不要なオブジェクトが残り続けることがあります。これが「メモリリーク」と呼ばれる現象で、システムのパフォーマンス低下や不安定化の原因となります。

`Set prj = Nothing` や `Set obj = Nothing` のように、オブジェクト変数を明示的に`Nothing`に設定することで、その参照を解放し、ガベージコレクション(不要になったメモリを自動的に回収する仕組み)が適切に機能するよう促します。これは、堅牢で安定したマクロを記述するための非常に重要な作法です。

`On Error GoTo` の重要性:堅牢なコードの第一歩

どんなに完璧なコードを書いたつもりでも、予期せぬエラーは発生し得ます。ファイルが存在しない、アクセス権がない、データが不正である、など、様々な要因が考えられます。`On Error GoTo ErrorHandler`のようなエラーハンドリングを導入することで、エラーが発生した場合でもマクロが突然停止することなく、適切なメッセージを表示したり、クリーンアップ処理(`Finally`ブロック)を実行したりすることができます。

実践的な活用方法:自動化の次のステップ

このマクロは、単体で実行するだけでも十分効果的ですが、さらに自動化を進めることで、その価値を最大限に引き出せます。

プロジェクトイベントへの組み込み(上級者向け)

Projectには、特定の操作が行われた際に自動的にマクロを実行する「イベントプロシージャ」という強力な機能があります。例えば、プロジェクトが閉じられる直前にこのクリーンアップマクロを実行するように設定すれば、常にファイルが最適な状態で保存されるようになります。

‘// ThisProject モジュールに記述します //

Private Sub Project_BeforeClose(ByVal pj As Project, Cancel As Boolean)
‘ プロジェクトが閉じられる前に、ファイル最適化マクロを呼び出します。
‘ これにより、常にクリーンな状態でプロジェクトファイルを保存できます。
If Not Cancel Then ‘ 閉じることがキャンセルされていない場合のみ実行
Call OptimizeProjectFile ‘ 上記で作成したマクロを呼び出します。
‘ 注意: Project_BeforeSave イベントで Save メソッドを直接呼び出すと無限ループになる可能性があります。
‘ BeforeClose イベントであれば、安全に保存処理を行えます。
End If
End Sub

【注意点】
`Project_BeforeClose`イベントは、プロジェクトが閉じられる際に発生します。このイベント内で`OptimizeProjectFile`を呼び出すことで、閉じる前に最適化と保存が行われます。
`Project_BeforeSave`イベントで`Save`メソッドを呼び出すと、`Save`が`BeforeSave`を再帰的に呼び出し、無限ループに陥る可能性があります。慎重に扱いましょう。初めは明示的なマクロ実行から慣れていくことをお勧めします。

定期的な実行の推奨

イベントプロシージャでの自動化は強力ですが、まずは月に一度、またはプロジェクトのフェーズが切り替わるタイミングなど、定期的に手動でこのマクロを実行することを習慣にしましょう。それだけでも、プロジェクトファイルの健康状態は大きく改善されます。

まとめ:Project VBAでプロジェクト管理を次のレベルへ

今日の記事では、Project VBAを使ってプロジェクトファイルを軽量化する「極限の知見」をお伝えしました。

  • Projectファイルが肥大化するメカニズムと、それが引き起こす問題点
  • `ActiveProject`、コレクション、アイテムといったProjectオブジェクトモデルの基本
  • `BuiltIn`プロパティを活用し、不要なカスタム定義を識別・削除する方法
  • `Application.ScreenUpdating = False`や`Set obj = Nothing`など、パフォーマンスと堅牢性を高めるための重要なVBAの作法

これらの知識は、単に今回の「ファイル軽量化」だけでなく、Project VBAを使ったあらゆる自動化の基礎となります。

「マクロの記録」から一歩踏み出し、オブジェクトのライフサイクルやパフォーマンスの重みを意識したコードを書けるようになれば、あなたはもう初心者ではありません。Project VBAを掌握し、プロジェクト管理のプロフェッショナルとして、あなたの業務を次のレベルへと引き上げていきましょう。

ここをクリアすれば、Project VBAの基本はバッチリですよ!あなたの挑戦を心から応援しています。
次回も、Project VBAの奥深い世界を一緒に探求していきましょう!

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