【入門編】【上級者向け】Project VBAにおけるカスタムフィールド操作のメモリリーク対策 – Project VBA解析バイブル

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

Project VBAを掌握する極限の知見:大量タスク処理でメモリを食いつぶさないための「オブジェクト解放術」

こんにちは。現場のコードを、もっと美しく、もっと速く。
今日は、Microsoft Project VBAの深淵へと足を踏み入れてみましょう。

「マクロの記録」でコードを書き始め、少しずつ複雑な処理ができるようになった。そんなあなたが次にぶち当たる壁――それは「処理がどんどん重くなる」「タスクが増えるとProjectが落ちる」という、目に見えない恐怖です。

実はこれ、プログラムの書き方ひとつで回避できる「メモリ管理」の問題なんです。今回は、カスタムフィールド(Task/Resource)を大量に操作する際に避けては通れない、メモリリーク対策について、その本質を伝授します。

ここをクリアすれば、あなたはもう「動けばいいマクロ」を書く人ではなく、「プロフェッショナルな自動化エンジニア」への階段を登ることになりますよ。

1. なぜ、あなたのProjectは「重く」なるのか?

まず、根本的な原理を理解しましょう。

Project VBAでタスク(`Task`)やリソース(`Resource`)を操作するとき、私たちは単に数字を書き換えているのではありません。裏側では、「COMオブジェクト」と呼ばれる、非常に巨大で複雑なデータの塊を、VBAから呼び出して操作しています。

イメージ図:図書館の貸出管理

想像してみてください。あなたは図書館の司書です。

  • タスクオブジェクト = 1冊の本
  • 変数への代入 = 本を借りて、机に置くこと

もし、あなたが「本を借りる(変数に代入する)」動作を1,000回繰り返したとします。読み終わったあとに「本を棚に戻す(メモリを解放する)」ことを忘れたらどうなるでしょうか?
図書館の机は本で溢れかえり、新しい本を置くスペースがなくなってしまいます。これがメモリリーク(メモリの漏洩)の正体です。

Projectのような巨大なアプリケーションでは、この「机の上の本」がメモリを占有し、最終的には「メモリ不足」で強制終了を引き起こすのです。

2. 初心者が陥る「メモリを食いつぶすコード」の典型例

まずは、よくある「惜しい」コードを見てみましょう。

' ❌ 良くない例:メモリ管理が疎かなコード
Sub BadExample()
    Dim t As Task
    Dim myTask As Task
    
    ' 大量のタスクをループ
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            ' オブジェクトを変数にセット
            Set myTask = t
            
            ' カスタムフィールド(Text1)に値を書き込む
            myTask.Text1 = "処理済み"
            
            ' ここで myTask を解放していない!
            ' ループが回るたびに、メモリ上に「参照の残りカス」が溜まっていく可能性がある
        End If
    Next t
    
    MsgBox "完了しました"
End Sub

何が問題なのか?

このコードの最大の問題は、`Set myTask = t` で取得したオブジェクトへの参照を、明示的に「使い終わったよ」とコンピュータに伝えていない点です。

ループの回数が多い場合、VBAのガベージコレクション(自動掃除機能)が追いつかず、Projectのメモリ使用量が右肩上がりに増えていく現象が発生します。

3. プロフェッショナルが実践する「メモリ解放の黄金律」

では、どう書けばいいのか。極限の安定性を求めるなら、以下の3つのステップを徹底してください。

1. オブジェクト変数は、使い終わったら即座に `Nothing` を代入する。
2. 計算処理(Calculate)のタイミングを制御する。
3. 画面更新と再計算を一時停止し、負荷を最小限にする。

これらを盛り込んだ、実戦的なコードを見てみましょう。

🚀 決定版:最適化されたカスタムフィールド操作コード

' ✅ プロフェッショナルな例:メモリ管理を徹底したコード
Sub OptimizedCustomFieldUpdate()
    Dim t As Task
    Dim targetTask As Task
    Dim taskCount As Long
    
    ' --- 準備:パフォーマンス向上のための設定 ---
    ' 画面更新を止めて、処理中のチラつきと負荷を軽減
    Application.ScreenUpdating = False
    ' 自動再計算を止める(これが重要!ループ中に毎回計算させない)
    Application.Calculation = pjCalculationManual
    
    On Error GoTo ErrorHandler ' エラー時に設定を元に戻すためのトラップ
    
    taskCount = 0
    
    ' --- メイン処理 ---
    For Each t In ActiveProject.Tasks
        ' タスクが存在しない(空行など)場合はスキップ
        If Not t Is Nothing Then
            
            ' 1. オブジェクトの参照をセット
            Set targetTask = t
            
            ' 2. カスタムフィールド(Text1)への書き込み
            ' ここでは例として、タスク名に接頭辞を付ける
            targetTask.Text1 = "[PROCESSED] " & targetTask.Name
            
            ' 3. 【重要】オブジェクトのライフサイクルを管理
            ' 処理が終わったら、即座に参照を解放する
            Set targetTask = Nothing
            
            taskCount = taskCount + 1
        End If
    Next t

    ' --- 後処理 ---
    ' 最後に一度だけ再計算を実行(ループ内で行わないのがコツ)
    Application.Calculate
    
    MsgBox taskCount & " 件のタスクを最適に処理しました。", vbInformation

CleanUp:
    ' 設定を元の状態に戻す(これを忘れるとProjectの挙動がおかしくなります)
    Application.ScreenUpdating = True
    Application.Calculation = pjCalculationAutomatic
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
    Resume CleanUp
End Sub

4. ここがプロの分かれ道:技術解説

なぜこのコードが「強い」のか。ポイントを整理しておきましょう。

① `Set targetTask = Nothing` の威力

ループの最後で `Nothing` を代入することで、コンピュータに対して「この本(オブジェクト)はもう使い終わりました。棚に戻していいですよ」と明確に伝えています。これにより、メモリの空き容量が常に一定に保たれます。

② `pjCalculationManual` による「計算爆発」の防止

これが最も見落としがちなポイントです。
カスタムフィールドの値を書き換えるたびに、Projectは「あ、値が変わった!プロジェクト全体を再計算しなきゃ!」と動いてしまいます。
1万件のタスクがある場合、1万回フル再計算が走る計算になります。これはメモリとCPUを極限まで消費します。
`Application.Calculation = pjCalculationManual` でこれを止め、最後に一括で `Calculate` する。この差が、処理時間を「数分」から「数秒」へと変えるのです。

③ エラーハンドリング(`On Error GoTo`)

メモリ管理や設定変更を行うコードでは、エラーが起きたときに「画面更新停止」や「手動計算モード」のまま放置されるのが一番の恐怖です。
`ErrorHandler` を用意し、どんなエラーが起きても必ず `CleanUp`(設定を元に戻す処理)を通るように設計するのが、一流の作法です。

まとめ:エンジニアとしての第一歩

いかがでしたか?
「ただ値を書き込むだけ」のコードと、「メモリのライフサイクルを意識した」コード。
その違いは、プロジェクトの規模が大きくなればなるほど、決定的な差となって現れます。

1. オブジェクトを使い終わったら `Nothing` で解放する。
2. 大量処理のときは `Calculation` を手動に切り替える。
3. エラーが起きても「元の設定に戻す」責任を持つ。

この3点を守るだけで、あなたの作るツールは劇的に安定します。
「動く」のその先にある、「安定して、速い」コードを目指して。

ここをクリアすれば、Project VBAの基本はバッチリですよ。
さあ、自信を持って次の自動化に挑戦してください!応援しています。

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