【テクニカル・上級編】【初心者向け】プロジェクト内のタスクをループ処理で全探索し、特定の条件でフラグを立てる基本手法 – Project VBA解析バイブル

スポンサーリンク

プロジェクトの「脈動」を制御せよ:Taskオブジェクト全走査の極意

Project VBA(Microsoft Project)の深淵へようこそ。

多くの者が `For Each t In ActiveProject.Tasks` と書き殴り、それで満足する。だが、君たちが相手にしているのは単なるデータの羅列ではない。プロジェクトという名の、刻一刻と状態を変える「生きたオブジェクトツリー」だ。

メモリリークを恐れ、再描画のオーバーヘッドを制御し、数十万行のタスクを高速に捌く。それが真のエンジニアの流儀だ。今日は、タスクの階層構造を効率的に走査し、条件に応じてフラグを立てるための「極限の作法」を伝授する。

1. オブジェクトライフサイクルの厳格な管理

VBAにおいて、`Task` オブジェクトをループで回す際、多くの初心者が犯す過ちは「暗黙的な参照の放置」だ。特にProjectのオブジェクトモデルは、参照が循環しやすく、複雑なマクロを繰り返すとメモリの解放が追いつかなくなる。

以下のコードでは、必ず参照を明示的にクリアし、かつ「再描画の抑制」によるパフォーマンスの最大化を図っている。

‘ プロジェクトのタスクを走査し、期間が10日を超える場合にカスタムフラグを立てる
Public Sub OptimizeTaskFlagging()
Dim proj As Project
Dim tsk As Task
Dim app As Object

‘ 画面更新を停止(高速化の鉄則)
Application.ScreenUpdating = False

Set proj = ActiveProject

‘ エラーハンドリングの徹底
On Error GoTo Cleanup

For Each tsk In proj.Tasks
‘ ヌルチェックとサマリータスクの除外(計算対象の選別)
If Not tsk Is Nothing Then
If Not tsk.Summary Then
‘ 期間が10日(80時間)を超える場合
If tsk.Duration > 4800 Then ‘ Project内部値は分単位
tsk.Flag1 = True
End If
End If
End If
Next tsk

Cleanup:
‘ 明示的なオブジェクト解放
Set tsk = Nothing
Set proj = Nothing

‘ 画面更新の復帰
Application.ScreenUpdating = True

If Err.Number <> 0 Then
MsgBox “想定外のエラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub

2. なぜ「全走査」は重いのか?

`ActiveProject.Tasks` を回す際、裏側で何が起きているか意識したことはあるか?
これは単なる配列のイテレーションではない。内部的には、プロジェクトの依存関係グラフ(WBS)を辿るクエリが走っている。

  • 依存関係(Predecessors)の罠: `Task.Predecessors` プロパティをループ内で多用すると、そのたびにCOM経由のコールが発生し、パフォーマンスは劇的に低下する。
  • 再帰の回避: 階層構造を深く掘り下げる場合、再帰呼び出しは避けるべきだ。スタックオーバーフローのリスクと、オブジェクト生成コストが嵩むからだ。

もし大規模なプロジェクト(数万タスク)を扱うなら、`Task` オブジェクトを直接操作するのではなく、一度 `Variant` 配列にIDと期間をロードし、メモリ上で処理した後に一括で書き込むのが、アーキテクトの定石である。

3. レガシー環境とWindows APIの接点

もし君が、さらに高度な制御(例えば、特定のタスク処理中にWindowsのタイマー割り込みを検知したり、プロセス優先度を一時的に上げたい)を望むなら、`Kernel32.dll` の力を借りる必要がある。

If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As LongPtr)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If

例えば、バックグラウンドでの外部システム連携(API呼び出しなど)がボトルネックになる場合、`Sleep` を挟むことでタスクスケジューラのCPU占有率を下げ、OS全体のレスポンスを維持できる。これこそが、単なるコード書きと「システム設計」の境界線だ。

4. 伝説のエンジニアからの忠告

1. 「何も触らない」という選択: プロジェクトファイルは壊れやすい。`Task.Flag` を書き換える前に、必ず変更前の値をバックアップする仕組みか、Undo(元に戻す)を意識したトランザクション制御を組み込め。
2. 型を信じるな: `tsk.ID` や `tsk.UniqueID` は混同しやすい。特に外部システムと連携する際は、必ず `UniqueID` を主キーとして扱うこと。
3. 文書化の呪い: コードのコメントには、「なぜそうしたか」を記せ。「タスクを走査している」などと書く必要はない。それはコードが語っている。

君たちが記述するVBAは、単なる自動化ツールではない。プロジェクトの進行を左右する、いわば「デジタルな司令塔」だ。その責任の重さを自覚し、一行一行に魂を込めてほしい。

健闘を祈る。

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