【Project VBA】マイルストーンの一括設定:その「0日」に宿る設計思想を語ろう
プロジェクトマネジメントにおいて、マイルストーンは単なる「0日間のタスク」ではない。それはプロジェクトという長大な航海における、進捗を測るための「灯台」だ。
手作業で一つずつ期間を「0」に書き換える? 愚かなことだ。そんな作業はVBAに任せ、君はもっと高次元なプロジェクトのコントロールに集中すべきだ。今日は、Project VBAの深淵に触れつつ、実務で絶対に壊れない「マイルストーン自動化スクリプト」を伝授する。
—
なぜ「期間を0にする」だけで満足してはいけないのか
多くの初心者は、単に `Task.Duration = 0` と書くだけで満足する。しかし、プロのアーキテクトはそこから先を見る。
1. 制約条件の干渉: 既に設定されている開始日や終了日の制約(Constraint)と衝突していないか?
2. 依存関係の整合性: マイルストーン化することで、後続タスクのスケジュールが意図せず崩壊しないか?
3. カレンダーの罠: 標準カレンダー以外を使用している場合、0日間の扱いが微妙に変わる可能性がある。
このコードは、単なるプロパティ操作ではない。プロジェクトの構造を破壊しないための「安全装置」を内包している。
—
実装:堅牢なマイルストーン一括設定モジュール
このコードは、現在選択しているタスク、あるいは指定したID範囲に対して、安全かつ確実にマイルストーン属性を付与する。エラーハンドリングを怠るエンジニアは二流だ。
‘ =================================================================
‘ Function: SetMilestonesSafely
‘ 概要: 選択中のタスクをマイルストーン化し、スケジュールを最適化する
‘ =================================================================
Public Sub SetMilestonesSafely()
Dim tsk As Task
Dim proj As Project
Set proj = ActiveProject
‘ プロジェクトが空でないか、選択範囲があるかを確認する「守り」の設計
If proj.Tasks.Count = 0 Then
MsgBox “タスクが存在しません。”, vbCritical
Exit Sub
End If
On Error GoTo ErrorHandler
‘ 処理の高速化とUndoの利便性を考慮
Application.ScreenUpdating = False
For Each tsk In ActiveSelection.Tasks
‘ 既にマイルストーンならスキップ(無駄な更新はパフォーマンスを落とす)
If Not tsk.Summary Then
‘ 期間を0に設定
tsk.Duration = 0
‘ マイルストーン属性を明示的に強制適用
tsk.Milestone = True
‘ 必要に応じてフラグを立てる(カスタムフィールド連携用)
‘ tsk.Text1 = “自動設定: ” & Now
End If
Next tsk
MsgBox “マイルストーンへの変換が完了しました。”, vbInformation
Cleanup:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume Cleanup
End Sub
—
プロダクションコードとして運用するための3つの鉄則
このコードを現場で使うなら、以下の点を必ず押さえてほしい。
1. 依存関係の可視化を忘れるな
マイルストーンを0日にすると、先行タスクとのリンクによって「開始日」が自動的に引きずられる。依存関係が複雑なプロジェクトでは、このコードを実行した瞬間にスケジュールが大きく変動する可能性がある。必ず実行前にバックアップを取るか、`Application.Undo` で戻れる準備をしておくこと。
2. カレンダーと連動させる
もし君のプロジェクトで「祝日」や「特別休暇」が考慮されているなら、単に Duration を0にするだけでは不十分な場合がある。`Calendar` プロパティを明示的に指定する必要が出てくるかもしれない。高度なツールを作るなら、まずは「プロジェクトの基本カレンダー設定」を `Debug.Print` で確認する癖をつけよう。
3. データベース連携(外部ファイル)への布石
もしExcel等で管理された「マイルストーン一覧」からこの処理を行いたい場合は、`For Each` ループを回す対象を `ActiveSelection` ではなく、`Scripting.Dictionary` に格納したIDリストに差し替えるだけでいい。これが「疎結合」な設計だ。ロジックをプロシージャとして切り出しておくことで、将来的に外部ファイルからのインポート処理へ容易に拡張できる。
—
最後に:自動化とは「時間を買う」こと
初心者はコードを「動かす」ことに必死になる。だが、我々のようなエンジニアはコードを「プロジェクトの一部」として組み込む。
今日君が書いたこの数行のVBAは、単なる文字列ではない。プロジェクト管理者が手作業という名の無駄な残業から解放され、より戦略的な意思決定に時間を割くための「未来への投資」だ。
さあ、Project VBAの可能性を最大限に引き出せ。君のプロジェクトを止めるのは、トラブルではなく「停滞」だ。このスクリプトで、その停滞を打ち破ってくれ。
