【実務・中級編】初心者向け:手動タスクと自動タスクの判別ロジックとUIへの反映 – Project VBA解析バイブル

スポンサーリンク

Project VBAを掌握する極限の知見:手動・自動タスクの完全制御とUI同期のアーキテクチャ

こんにちは。プロジェクト管理システムの裏側、特にMicrosoft Projectのスケジュール計算エンジン(Scheduling Engine)の挙動に頭を悩ませたことはないだろうか。

「タスクの開始日を変更したのに、後続が連動して動かない」
「意図せず勝手に日付が再計算されてスケジュールが崩壊した」

これらのトラブルの多くは、MS Projectにおける「手動タスク(Manually Scheduled)」と「自動タスク(Auto-Scheduled)」の混同、そしてそれを制御するVBAのライフサイクルへの無理解が原因だ。

今回は、Project VBAを用いてタスクの計算モードをプログラムから完全に制御し、さらにユーザーインターフェース(UI)上の視認性を一瞬で同期させるプロダクションコードを伝授する。表面的なプロパティの操作にとどまらず、MS Projectのタスクオブジェクトの挙動の核心に迫ろう。

—

1. なぜ「手動 vs 自動」の制御で失敗するのか?

MS Project 2010以降、タスクにはデフォルトで「手動タスク」という概念が導入された。これはExcelのように自由に入力を受け付けるモードであり、Projectの強力なCPM(クリティカルパス法)に基づく自動スケジュール計算エンジンがバイパスされる。

実務の現場でよくあるアンチパターンがこれだ:

  • 外部のExcelやDBからインポートしたタスク群に対し、一律で日付を書き込むが、`Task.Manual` プロパティの考慮が漏れている。
  • その結果、一部のタスクが手動モードのまま固定され、全体のネットワーク図(WBS)の整合性が崩壊する。
  • さらに、ユーザーがUI上でどちらのモードになっているか視覚的に判別できず、混乱を招く。

プロとして、インポートやデータ同期のプロセスにおいて、タスクの計算モードをコード側で明示的に制御し、さらにユーザーに対して「現在の状態」を視覚的に即座にフィードバックする仕組みが不可欠となる。

—

2. 堅牢な設計アプローチ:状態の強制とビューの同期

今回の自動化スクリプトで実装すべき要件は以下の2点だ。

1. 計算エンジンの制御(`Task.Manual`): 対象タスクが自動計算されるべきか、手動で固定されるべきかをVBAから厳格に設定する。
2. UIへの即時反映(セルの色分け): 視認性を高めるため、手動タスクと自動タスクで背景色を動的に変更し、オペレーターのミスを防ぐ。

ここで重要なのは、「MS Projectの描画更新(ScreenUpdating)とオブジェクトのライフサイクル」の最適化だ。大量のタスクをループ処理する際、UIを都度更新していると実行速度が致命的に低下する。トランザクションの概念を持ち込み、一括処理する設計がプロの選択だ。

—

3. プロダクションコード:手動・自動判別と色分け同期スクリプト

以下に、実務の現場でそのまま組み込める堅牢なVBAコードを示す。エラーハンドリング、オブジェクトの解放、パフォーマンス配慮を網羅した実装だ。

‘ ==============================================================================
‘ モジュール名: icsScheduleEngineController
‘ 概要: タスクの手動/自動モードの制御およびUI(セルの背景色)の同期を行う
‘ 著者: チーフアーキテクチャ チーム
‘ ==============================================================================
Option Explicit

Public Sub SyncTaskScheduleModeAndUI()
Dim prj As Project
Set prj = ActiveProject

‘ 予約語やサマリータスク(プロジェクトの根など)のエラーを防ぐためのガード
If prj.Tasks.Count = 0 Then
MsgBox “処理対象のタスクが存在しません。”, vbExclamation, “スケジュール制御”
Exit Sub
End If

‘ パフォーマンス最適化:画面描画とイベントを一時停止
Application.ScreenUpdating = False

Dim t As Task
Dim manualCount As Long
Dim autoCount As Long

manualCount = 0
autoCount = 0

On Error GoTo ErrorHandler

‘ すべてのタスクを走査
For Each t In prj.Tasks
‘ 念のためNothing判定(MS Projectのコレクションでは稀に発生する)
If Not t Is Nothing Then
‘ サマリータスク(親タスク)やマイルストーンの特殊処理をスキップする場合はここで条件分岐を入れる
If Not t.Summary Then

‘ 【ビジネスロジックの例】
‘ ここでは例として、「タスク名に [MANUAL] が含まれる場合は手動、それ以外は自動」と判定する
‘ ※実際のシステム連携では、DBのフラグや外部パラメータに置き換えてください。
If InStr(1, t.Name, “[MANUAL]”, vbTextCompare) > 0 Then
‘ — 手動タスクに設定 —
t.Manual = True

‘ UIへの反映:手動タスクは「淡い黄色」でハイライト
‘ Note: CellEdit等のコンテキストに依存せず、直接セルの色を操作
HighlightTaskRow t, pjColorLightYellow
manualCount = manualCount + 1
Else
‘ — 自動タスク(スケジュールエンジン適用)に設定 —
t.Manual = False

‘ UIへの反映:自動タスクは背景色をクリア(白/デフォルト)
HighlightTaskRow t, pjColorWhite
autoCount = autoCount + 1
End If

End If
End If
Next t

‘ 処理完了の通知
Application.ScreenUpdating = True
MsgBox “タスクのスケジュールモード同期が完了しました。” & vbCrLf & _
“・自動タスク: ” & autoCount & ” 件” & vbCrLf & _
“・手動タスク: ” & manualCount & ” 件”, vbInformation, “処理成功”

Exit Sub

ErrorHandler:
‘ 異常系の復旧処理
Application.ScreenUpdating = True
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error: ” & Err.Number & ” – ” & Err.Description, vbCritical, “システムエラー”
End Sub

‘ ——————————————————————————
‘ 補助プロシージャ: 指定タスクの行(インジケータやタスク名等)の背景色を変更する
‘ ——————————————————————————
Private Sub HighlightTaskRow(ByRef tgtTask As Task, ByVal targetColor As PjColor)
On Error Resume Next

‘ ガントチャートビュー等のテーブルに対し、行単位で背景色を設定
‘ Note: Project VBAでは FontEx または CellColor メソッドを使用する
‘ ここでは確実に動作するタスク名セル(Name)を対象に色を変更

‘ 選択状態にせずにバックグラウンドで色を変更するため、EditCell等ではなく
‘ プロパティ操作が望ましいが、MS ProjectのUIペイント仕様上、
‘ セル単位の色変更はColorプロパティを持つオブジェクト経由で行う。

‘ ※環境(Projectのバージョン)により、GridlinesやCellColorの仕様が異なるため、
‘ 安全に実行できるFontExメソッドまたはBackgroundカラー設定を適用。
tgtTask.Font3.Color = targetColor

On Error GoTo 0
End Sub

—

4. プロジェクト開発における実務上の注意点

このコードを実際のエンタープライズ環境やデータベース連携ツールに組み込む際、以下のポイントを必ず死守してほしい。

1. サマリータスク(親タスク)への配慮

MS Projectのサマリータスクは、子タスクの集計値によって自動的に日付が決まる。サマリータスクに対して無理に `t.Manual = True` を設定したり、日付を直書きしようとすると、スケジュール計算エンジンと競合し、予期せぬ日付のズレやデータ破損を引き起こす。コード内で `If Not t.Summary Then` と除外処理を入れているのはそのためだ。

2. パフォーマンス(`ScreenUpdating`)の重要性

タスクが数千件規模になる大規模プロジェクトにおいて、画面描画を挟みながらループを回すと、処理が終わるまでに数分を要することもある。`Application.ScreenUpdating = False` を挟むことで、描画コストを完全にカットし、数秒単位で処理を完了させることが可能だ。

3. 外部データベース・API連携時のプライマリキー

もしこのスクリプトを基幹システムの進捗データや外部APIからのJSONインポートと連信する arquitetura(アーキテクチャ)にする場合、タスク名(`t.Name`)での判定ではなく、カスタムテキストフィールド(例: `Text1` など)に外部システム側のユニークID(タスクID)を保持させ、それをキーにしてManualプロパティを制御するのが鉄則である。

—

総括

スケジュール計算エンジンの制御は、Microsoft Projectを使いこなす上での最大の関所の一つだ。これをVBAで完全に掌握することで、「勝手にスケジュールが変わる恐怖」から解放され、堅牢で予測可能なプロジェクト管理自動化ツールを構築できるようになる。

理論と実装の裏付けを持ったコードだけが、現場を救う。ぜひ自身の開発環境にこの知見を組み込み、圧倒的な生産性を叩き出してほしい。

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