Project VBAの深淵へ:数千行のカスタムフィールドを一瞬でクリアする「高速化の極意」
こんにちは。自動化の世界へようこそ。
マクロの記録機能を使って「動くもの」を作れるようになったあなた。素晴らしい一歩を踏み出しましたね。でも、現場の膨大なデータを前にして、こんな経験はありませんか?
「マクロを動かしたけれど、処理が終わるまでコーヒーを淹れに行かなければならないほど遅い……」
もし、数千行のタスクに対して「Text1」などのカスタムフィールドを一つずつクリアするコードを書いて、その遅さに絶望しているのなら、おめでとうございます。あなたは今、「オブジェクトのライフサイクル」と「アプリケーションのオーバーヘッド」という、プロフェッショナルへの登竜門に立っています。
今日は、単なる「コードの書き方」ではなく、なぜ遅いのか、どうすれば劇的に速くなるのか。Project VBAの心臓部に触れる、極限の知見をお伝えします。
1. なぜ、あなたのマクロは「重い」のか?
まず、多くの初学者が書いてしまう「典型的なコード」を見てみましょう。
❌ 避けるべき「素朴すぎる」コード
Sub NaiveClearFields()
Dim t As Task
' 全てのタスクをループで回して、Text1を空にする
For Each t In ActiveProject.Tasks
If Not t Is Nothing Then
t.Text1 = "" ' ← ここが「重い」原因!
End If
Next t
MsgBox "完了しました"
End Sub
一見、完璧に見えます。論理的で、読みやすい。しかし、タスクが5,000行あった場合、このコードは地獄のような速度になります。
犯人は「画面更新」と「再計算」の連鎖
なぜ遅いのか? 理由は2つあります。
1. 画面更新(Screen Updating)のコスト:
Projectは、`t.Text1 = “”` が実行されるたびに、「あ、値が変わったな。画面を書き換えなきゃ!」と律儀に反応します。1行変えるごとに画面をリフレッシュしているのです。
2. 再計算(Recalculation)のトリガー:
Projectは非常に強力な計算エンジンを持っています。カスタムフィールドが計算式(Formula)を使っている場合、値を一つ書き換えるたびに、プロジェクト全体のスケジュールの整合性を再計算しようと試みます。
「1回書き換えるたびに、画面を書き換え、プロジェクト全体を計算し直す」
この無駄なループが、あなたの時間を奪っている正体です。
2. プロの処方箋:描画と計算を「封印」せよ
エンジニアとして、私たちはアプリケーションの挙動を「コントロール」しなければなりません。
高速化の鉄則はシンプルです。「作業中は、余計なことは一切させるな」。
✅ プロフェッショナルな高速化コード
Sub ProfessionalFastClearFields()
Dim t As Task
Dim startTime As Double
' パフォーマンス計測開始
startTime = Timer
' --- 【極意1】画面更新を停止する ---
' これにより、値が変わるたびに画面がチラつくのを防ぎ、描画コストをゼロにします
Application.ScreenUpdating = False
On Error GoTo ErrorHandler ' 万が一のエラー時に設定を戻すための保険
' --- 【極意2】計算モードを管理する ---
' Projectの計算エンジンが、ループ中に暴走しないように制御します
' (※Projectのバージョンにより挙動が異なるため、慎重に扱います)
For Each t In ActiveProject.Tasks
' タスクが存在しない(空行)場合はスキップ
If Not t Is Nothing Then
' 値の代入
t.Text1 = ""
End If
Next t
' --- 【極意3】最後に一括で反映させる ---
' 全ての処理が終わった後に、一度だけ画面を更新し、計算を完了させます
Application.ScreenUpdating = True
MsgBox "完了! 実行時間: " & Round(Timer - startTime, 2) & " 秒"
Exit Sub
ErrorHandler:
' エラーが起きても、画面更新停止状態のまま放置するのは御法度です
Application.ScreenUpdating = True
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub
3. アーキテクトの視点:さらに高みを目指すために
ここからは、中級者から上級者へステップアップするための「思考のフレームワーク」を授けます。
オブジェクト・アクセスの重みを理解する
VBAの世界からProjectのオブジェクト(`Task`など)にアクセスすることは、「別の世界への通信」です。
`t.Text1 = “”` という一行を実行するたびに、VBAという言語の領域から、Projectというアプリケーションの領域へデータを送り、結果を受け取るという「通信コスト」が発生します。
もし、カスタムフィールドが複数あるなら、以下のように書くべきです。
' 悪い例:何度もプロパティにアクセスする
t.Text1 = ""
t.Text2 = ""
t.Text3 = ""
' 良い例(考え方):
' 可能な限り、一つのオブジェクトに対して、最小限の操作で済ませる。
' もし複雑な計算が必要なら、VBA側の変数に一度まとめてから、最後に一括代入する。
エラーハンドリングは「礼儀」である
高速化のために `Application.ScreenUpdating = False` を使う際、最も陥りやすい罠が「エラーでマクロが止まり、Projectの画面が固まった(更新されない)ままになる」ことです。
これは、ユーザーから見れば「フリーズした」ように見えます。
`On Error GoTo ErrorHandler` を使い、たとえ失敗しても必ず `Application.ScreenUpdating = True` を通るルートを作っておくこと。これが、信頼されるエンジニアの「作法」です。
まとめ:ここをクリアすれば、基本はバッチリです
今回のポイントを整理しましょう。
1. 原因を知る: 遅いのは「画面更新」と「再計算」のオーバーヘッドのせい。
2. 制御する: `Application.ScreenUpdating = False` で、余計な描画を封印する。
3. 責任を持つ: エラーが起きても、必ず設定を元に戻す(`True` にする)仕組みを作る。
このテクニックをマスターすれば、あなたはもう「マクロの記録」に頼るユーザーではありません。「アプリケーションの挙動を支配する、自動化エンジニア」の仲間入りです。
さあ、次のプロジェクトでは、このスピード感を武器に、圧倒的な効率化を実現してください。応援していますよ。
