【入門編】大規模プロジェクトでVBA実行速度を劇的に向上させる「画面更新停止」と「計算モード制御」 – Project VBA解析バイブル

スポンサーリンク

こんにちは!プロジェクト管理の現場で、日々奮闘されていることと思います。

「マクロの記録」でVBAの世界に足を踏み入れ、いざ数千行もある巨大なWBS(タスクの階層構造)をコードで自動制御しようとしたとき……。
「あれ、画面が真っ白になって固まった……?」
「終わったと思ったら、コーヒーを3杯飲み干すくらいの時間が経っていた……」

そんな恐怖を体験したことはありませんか?

大規模なプロジェクトデータを扱うとき、VBAのデフォルト設定のままループを回すと、Excelと同じようにMicrosoft Project(MS Project)も盛大にフリーズします。なぜなら、VBAが1行動かすたびに「画面の描き直し」と「複雑なタスク間のスケジュール再計算(依存関係のチェック)」を律儀に裏で行っているからです。

今回は、ここを完全にコントロールし、処理速度を爆速化させる極限のテクニックを伝授します。ここをクリアすれば、あなたのVBAスキルは「初心者」から「現場を救うエンジニア」へと一気にステージが上がりますよ。しっかりついてきてくださいね!

なぜ巨大プロジェクトのVBAは遅くなるのか?

まず、敵を知ることから始めましょう。
MS ProjectのVBAが遅くなる原因は、主に以下の2つです。

1. 画面の描画(ScreenUpdating)
タスクが1行追加・変更されるたびに、ガタガタとガントチャートやテーブルの表示を更新しようとするため。
2. 自動計算の嵐(Calculation / Task Dependencies)
数千件あるタスクの「前提条件(先行タスク)」や「制約条件」を、たった1行の変更のたびに全再計算しようとするため。

人間で例えるなら、1000個の荷物を運ぶのに、1個運ぶたびに「これで全体図は合っているか?」と全身のレントゲンを撮り直しているようなものです。そりゃあ疲弊して固まりますよね。

これを解決するアプローチはシンプルです。
「作業中は画面の更新を止め、計算もすべてストップさせ、最後に一気に完了させる」。これだけです。

爆速化を実現する魔法の3点セット

Project VBAにおいて、処理を高速化するための基本方針は以下の3行に集約されます。

‘ 1. 画面の更新を止める
App.ScreenUpdating = False

‘ 2. 自動計算を止める(手動計算モードにする)
App.Calculation = pjCalculationManual

‘ — ここに重たい処理(数千行のループなど)を書く —

‘ 3. 設定を元に戻し、最後に一度だけ再計算させる
App.Calculation = pjCalculationAutomatic
App.ScreenUpdating = True
App.CalculateAll ‘ 明示的に全体を再計算

これだけで、処理時間が数分から「数秒」に短縮されることも珍しくありません。

【実践】数千行のタスクを一網打尽にするサンプルコード

それでは、実際の現場でそのままコピペして使える、堅牢で美しいコードを見てみましょう。
今回は、大量のタスクに対して一括で処理を行い、フリーズを防ぐテンプレートを用意しました。

Sub OptimizeTaskProcessingDemo()
‘ —————————————————————-
‘ 目的: 大規模なタスク操作を極限まで高速化するテンプレート
‘ —————————————————————-

Dim t As Task
Dim startTime As Double
startTime = Timer ‘ 処理時間計測用

‘ エラー時にも必ず設定が戻るようにするための安全策(トランザクション的思考)
On Error GoTo ErrorHandler

‘ 【重要】パフォーマンス向上のための設定オフ
‘ —————————————————————-
App.ScreenUpdating = False ‘ 画面描画を停止
App.Calculation = pjCalculationManual ‘ 自動計算を停止
‘ —————————————————————-

‘ デバッグ用:現在のタスク数を確認
MsgBox “処理を開始します。対象タスク数: ” & ActiveProject.Tasks.Count, vbInformation

‘ 【メイン処理のシミュレーション】
‘ 数千行あると仮定したタスクをループ処理
For Each t In ActiveProject.Tasks
If Not t Is Nothing Then
‘ 例:すべてのタスクのテキストフィールドに特定の文字を付与する
‘ ※実際にはここにWBSの階層構造構築や依存関係設定が入ります
t.Text1 = “optimized”

‘ 注意: ループ内で DoEvents や MsgBox を絶対に入れないこと!
‘ 描画が強制復帰して爆速化の効果が台無しになります。
End If
Next t

‘ 【重要】設定を元に戻し、一括再計算を実行
‘ —————————————————————-
App.Calculation = pjCalculationAutomatic ‘ 自動計算を元に戻す
App.ScreenUpdating = True ‘ 画面描画を再開

‘ 止めている間に変更されたスケジュールを一括で再計算させる
App.CalculateAll
‘ —————————————————————-

‘ 完了メッセージ
MsgBox “処理が完了しました! 処理時間: ” & Format(Timer – startTime, “0.00”) & “秒”, vbInformation
Exit Sub

ErrorHandler:
‘ 万が一エラーが発生した際、画面や計算が止まったままになるのを防ぐための救済措置
App.ScreenUpdating = True
App.Calculation = pjCalculationAutomatic
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical

End Sub

コードの解説とプロの知見

1. `On Error GoTo ErrorHandler` の絶対死守
プログラミング初心者がやりがちなミスが、「`ScreenUpdating = False` にしたままエラーでマクロが強制終了し、MS Projectの画面が二度と動かなくなる」という現象です。エラーハンドラを用意し、万が一の時でも必ず設定がデフォルト値に戻るようにする配慮は、プロのエンジニアとしてのマナーです。
2. ループ内の `DoEvents` は厳禁
Excel VBAなどでは「フリーズ防ぎに `DoEvents` を入れろ」と教わることがありますが、Project VBAの高速化においては逆効果です。描画の割り込みが発生し、せっかくの最適化が無駄になります。
3. 最後に必ず `App.CalculateAll` を呼ぶ
計算モードを `pjCalculationManual` にしている間は、タスクの依存関係(先行・後続関係)による日付のズレなどが裏で自動調整されません。処理の最後に `CalculationAutomatic` に戻した上で、`CalculateAll` を明示的に叩くことで、プロジェクト全体の整合性を完璧に保つことができます。

陥りやすい罠とエラー対策

罠1:「あれ、コードを実行しても画面が変わらない……」

`ScreenUpdating = False` の間は、タスクが追加されてもガントチャートは一切動きません。コードがフリーズしているように見えるかもしれませんが、裏で猛烈に働いています。不安になる気持ちを抑え、終わった後の `MsgBox` を信じて待ちましょう。

罠2:オブジェクトの判定抜け

MS Projectの `ActiveProject.Tasks` には、途中で削除されたタスクの「空きスロット(Nothing)」が含まれていることがあります。ループを回すときは必ず `If Not t Is Nothing Then` でヌルチェックを入れるのが、バグを防ぐ鉄則です。ここをサボると、容赦なく「オブジェクト変数が設定されていません」というエラーの洗礼を受けます。

ここをクリアすれば、Project VBAの基本はバッチリですよ!

お疲れ様でした!
今回学んだ「画面更新停止」と「計算モード制御」は、数千行規模の大規模WBSを扱う現場において、知らないと仕事にならないレベルの必須教養です。

マクロの記録の向こう側にある「システムを思い通りに支配する感覚」、少しずつ掴めてきたのではないでしょうか?
このテクニックをあなたのプロジェクト管理ツールに組み込めば、どんなに巨大なWBSの自動生成や依存関係の構築であっても、ストレスフリーで一瞬のうちに完了させることができます。

明日からの実務で、ぜひこのコードを試してみてくださいね。あなたの開発ライフが、よりスマートで快適なものになることを応援しています!

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