【入門編】【上級者向け】大規模プロジェクトにおけるカスタムフィールドの計算負荷を最適化する – Project VBA解析バイブル

スポンサーリンク
スポンサーリンク

大規模プロジェクトの沈黙を破る:Project VBA カスタムフィールド計算の最適化術

こんにちは!業務自動化の世界へようこそ。

プロジェクトの規模が大きくなってくると、誰もが一度は直面する壁があります。それは、「MS Projectの動作が、まるで泥沼の中を歩いているかのように重くなる」という現象です。

「カスタムフィールドに数式を入れただけなのに」「タスクを一つ動かしただけで、画面がフリーズした……」

もしあなたが今、そんな悩みを抱えているとしたら、おめでとうございます。あなたは「マクロの記録」という初級ステージを卒業し、「オブジェクトの挙動を制御する」というプロフェッショナルな領域への入り口に立っています。

今日は、伝説的なアーキテクトが現場で実践している、カスタムフィールドの計算負荷を劇的に軽減する「極限の最適化手法」を伝授しましょう。

1. なぜ、あなたのプロジェクトは重くなるのか?

まず、敵の正体を知ることから始めましょう。

MS Projectには「カスタムフィールド」という非常に強力な機能があります。`Text1` や `Number1` といったフィールドに `[Duration] * 1.2` のような数式(Formula)を書き込むことができます。

これ自体は非常に便利ですが、大規模プロジェクト(タスク数が数千、数万に及ぶ場合)では、以下の「再計算の連鎖(Recalculation Loop)」が牙を剥きます。

【図解】再計算の悪循環

1. ユーザーの操作: タスクの期間を変更する。
2. エンジンの起動: MS Projectが「あ、データが変わった!再計算しなきゃ」と判断。
3. 数式の走査: すべてのタスクのカスタムフィールドに設定された数式を一つずつ評価。
4. 依存関係の連鎖: 数式の計算結果が変わったことで、さらに他の計算やスケジュールに影響が出る……。
5. CPUの悲鳴: このプロセスが、一つの変更に対して何度も、あるいは全タスクに対して何度も繰り返される。

つまり、「数式(Formula)は、便利だが『受動的』で制御不能な爆弾」なのです。

2. 最適化の極意: 「数式」から「値の書き込み」へ

プロフェッショナルなエンジニアは、こう考えます。
「Projectの計算エンジンに任せるのではなく、VBAで計算して『結果の値』だけを叩き込めばいい」

これを実現するための戦略が、「計算モードの制御」と「静的値への置き換え」です。

戦略のステップ

1. 計算を止める: `Application.Calculation = pjManual` で、プロジェクトの自動計算を一時停止します。
2. VBAで計算する: 数式で行っていた計算を、VBAのコード内で高速に処理します。
3. 結果を書き込む: 計算結果を、数式ではなく「ただのテキストや数値」としてカスタムフィールドに書き込みます。
4. 計算を再開する: 最後に `Application.Calculate` で、必要な部分だけを整合させます。

3. 実践: 劇的に速くなる最適化コード

それでは、具体的なコードを見てみましょう。
例えば、「タスクのコストとリスク係数を掛け合わせた『重み付きコスト』をカスタムフィールド(Number1)に算出する」というシナリオを想定します。

❌ 初心者がやりがちな「重い」コード

(数式が設定されたフィールドに対して、一つずつ値を読み書きしようとする、あるいは数式に頼り切るパターン)

✅ プロが書く「高速」な最適化コード

Sub OptimizeCustomFieldCalculation()
    Dim t As Task
    Dim startTime As Double
    Dim taskCount As Long
    
    ' 実行時間の計測開始(パフォーマンス確認のため)
    startTime = Timer
    
    ' --- [重要] ステップ1: 計算モードを「手動」に切り替える ---
    ' これにより、タスクを更新するたびに発生する自動再計算を封じ込めます
    Application.Calculation = pjManual
    
    On Error GoTo ErrorHandler
    
    ' プロジェクト内のタスクをループ処理
    For Each t In ActiveProject.Tasks
        ' 空のタスク(サマリータスクの隙間など)はスキップ
        If Not t Is Nothing Then
            
            ' --- [重要] ステップ2: VBA内で計算ロジックを完結させる ---
            ' カスタムフィールドに「数式」が入っているのではなく、
            ' ここで計算した「結果」を直接書き込むのがポイントです。
            
            Dim riskFactor As Double
            Dim baseCost As Double
            
            ' 例えば、Text1に「1.5」のようなリスク係数が入っていると仮定
            ' Val関数で数値に変換して計算
            riskFactor = Val(t.Text1)
            If riskFactor = 0 Then riskFactor = 1 ' 係数が空なら1とする
            
            baseCost = t.Cost
            
            ' --- [重要] ステップ3: 結果を「値」として書き込む ---
            ' Number1フィールドに、計算済みの数値だけを代入
            ' これにより、Number1自体は「数式」ではなく「ただの数字」になります
            t.Number1 = baseCost * riskFactor
            
        End If
    Next t

    ' --- [重要] ステップ4: 計算モードを「自動」に戻し、一括再計算 ---
    Application.Calculation = pjAutomatic
    Application.Calculate
    
    MsgBox "計算完了!" & vbCrLf & _
           "処理時間: " & Round(Timer - startTime, 2) & " 秒", vbInformation, "エンジニアの成果"
    
    Exit Sub

ErrorHandler:
    ' エラーが起きても、計算モードを自動に戻さないとProjectが操作不能になるため必須
    Application.Calculation = pjAutomatic
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

4. ここがエンジニアの腕の見せ所(解説)

このコードには、プロとして押さえておくべき3つのエッセンスが詰まっています。

① `Application.Calculation = pjManual` の魔力

これこそが最適化の鍵です。大規模プロジェクトにおいて、ループの中で一つタスクを更新するたびにMS Projectが「再計算」を走らせていたら、終わりが見えません。まず「黙らせる」こと。これが制御の第一歩です。

② 「数式」ではなく「計算結果」を流し込む

カスタムフィールドのプロパティに `[Cost]*[Text1]` と書いておくと、Projectは常に監視を続けます。しかし、VBAで `t.Number1 = 計算結果` と書いてしまえば、そのフィールドはただの「数字」です。監視する必要がなくなるため、動作が圧倒的に軽くなります。

③ エラーハンドリングの重要性

ここを忘れると、マクロがエラーで止まった瞬間、MS Projectが「手動計算モード」のまま固まってしまいます。 「数値を入力しても、スケジュールが全く動かない!」というパニックを防ぐために、`ErrorHandler` で必ず `pjAutomatic` に戻す処理を入れておきましょう。これは現場での「作法」です。

まとめ: 次のステージへ

いかがでしたか?

「マクロの記録」で得たコードは、いわば「操作の録画」です。それに対し、今回学んだ手法は「システムの構造を理解した上での制御」です。

1. 自動計算を止める
2. メモリ上で計算する
3. 結果を値として書き込む
4. 自動計算を再開する

このフローをマスターすれば、あなたはもう「重いプロジェクト」に怯えることはありません。

「なぜ動くのか」だけでなく、「どうすればもっと効率的に動くのか」。その視点を持つことが、伝説のエンジニアへの最短ルートです。

さあ、あなたのプロジェクトを、光のような速さで動かしてみましょう!応援していますよ。

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