Project VBAの深淵:WBSを自在に操る「タスク走査」の極意
業務自動化を志すエンジニア諸君。MS ProjectのVBAを触り始めたばかりの君たちが、最初に直面する壁。それが「タスクの全探索」だ。
「とりあえずループを回せばいいんでしょ?」——その安易な思考が、数万行のプロジェクトファイルを開いた瞬間にメモリリークという名の墓穴を掘ることになる。今日は、初心者から脱却し、実務レベルの堅牢なコードを書くための「プロの作法」を伝授しよう。
—
1. なぜ「For Each」でなければならないのか
Project VBAにおいて、タスクへのアクセス方法はいくつか存在する。インデックス指定(`ActiveProject.Tasks(i)`)は、一見直感的だが、フィルタリングされた状態やWBSの階層構造が複雑な場合、予期せぬ挙動を引き起こす。
我々が採用するのは `For Each` ループ だ。これには明確な理由がある。
- イテレータの安全性: プロジェクト内のタスクオブジェクトを一つずつ安全に取得する。
- 可読性と保守性: 「何番目」という物理的な位置ではなく、「タスクそのもの」を扱うため、コードがビジネスロジックに直結する。
—
2. 【プロダクションコード】堅牢なタスク走査の実装
単に条件分岐を書くだけではない。エラーハンドリングとオブジェクトの健全性を考慮した、業務でそのまま使えるテンプレートを提示する。
‘ ———————————————————
‘ プロジェクト内の長期間タスクを自動検知しフラグを立てる
‘ ———————————————————
Sub FlagLongDurationTasks()
Dim tsk As Task
Dim thresholdDays As Long
‘ 閾値の設定(保守性を考慮し、マジックナンバーを避ける)
thresholdDays = 10
‘ 処理の高速化:画面更新の停止(大規模プロジェクトでは必須)
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
For Each tsk In ActiveProject.Tasks
‘ 1. 空行(Summary Task等)を除外する「防衛的プログラミング」
If Not tsk Is Nothing Then
‘ 2. 期間が閾値を超えているか判定
‘ Durationは分単位で保持されるため、日単位に換算
If (tsk.Duration / 480) > thresholdDays Then
‘ 3. カスタムフィールド(Text1)にフラグを書き込み
tsk.Text1 = “要確認: 長期タスク”
tsk.TaskColor = pjRed ‘ 視覚的に強調
Else
tsk.Text1 = “”
tsk.TaskColor = pjAutomatic
End If
End If
Next tsk
CleanExit:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
—
3. 「動く」のその先へ:実務で必ず守るべき3つの鉄則
コードをコピペして満足するのは素人だ。現場で生き残るために、以下の3点を脳に刻んでおいてほしい。
① 画面更新の抑制(`ScreenUpdating`)
数千のタスクがあるファイルで、ループのたびにGUIを更新すれば、処理時間は数倍に跳ね上がる。`Application.ScreenUpdating = False` を忘れるエンジニアは、現場では「リソースの浪費家」と見なされる。
② 防衛的プログラミング(`If Not tsk Is Nothing`)
MS Projectのタスクリストには、削除されたタスクの残骸や、参照できない不正なオブジェクトが潜んでいることがある。`For Each` でイテレートする際、必ず `Nothing` チェックを通すこと。これがクラッシュを防ぐ唯一の盾だ。
③ 外部データ連携の注意点
今回のコードを応用して「ExcelやDBからタスク情報を読み込み、Projectに書き込む」という自動化を考えるだろう。その際、「Projectの再計算エンジン」を意識してほしい。
- 大量のタスクを更新する際は、`Calculation = pjManual` に設定し、すべての更新が終わった後に `CalculateAll` を呼び出す。これが、巨大なプロジェクトを扱う上での「大人の嗜み」である。
—
最後に:エンジニアとしてのマインドセット
VBAは古臭い言語だと言う者もいるが、MS Projectの内部オブジェクトモデルを操る力は、まさに「プロジェクトの心臓部を直接チューニングする」行為だ。
今回紹介したコードは、あくまで「入り口」に過ぎない。次はタスクの依存関係(`TaskDependencies`)を探索し、先行タスクに遅延が発生した場合に後続タスクへ自動でフラグを伝播させるロジックに挑戦してほしい。
君たちが書く一行のコードが、何百人のプロジェクトメンバーの作業を最適化し、納期という名のプレッシャーから彼らを救い出す。その誇りを胸に、今日もキーボードを叩いてくれ。
君の自動化ツールが、プロジェクトの成功を支える一助となることを期待している。
