【実務・中級編】計算エンジンの挙動を制御する隠し設定:VBAで操作可能なProjectオプション群 – Project VBA解析バイブル

スポンサーリンク

MS Project VBAを極める:計算エンジンの挙動を支配する隠し設定とプロダクション設計

開発プロジェクトのリーダーたるもの、スケジュール管理ツールを「言われた通りに動かすだけのオモチャ」扱いにしているようでは失格だ。MS Projectの裏側には、タスクの依存関係、リソースの負荷、そして数式によるスケジューリングを司る「計算エンジン」が鎮座している。

特に大規模な工程表をVBAで一括生成・更新する際、この計算エンジンが無駄にステップごとに再計算を行い、パフォーマンスを著しく低下させたり、意図しない制約条件(ASAP / ALAPなど)のデフォルト挙動によってスケジュールが歪む現象に頭を悩ませたことはないだろうか。

今回は、`Application.Options`系プロパティを駆使し、プロジェクトの計算エンジンをプログラム側から完全に掌握するための極限の知見を授けよう。

—

1. なぜ「デフォルトの計算挙動」に頼るべきではないのか?

実務において、VBAからタスクを一括追加・編集するマクロを書くとき、多くの初心者が陥る罠がある。それは「タスクを追加するたびにプロジェクトが勝手に再計算を行う」という仕様を放置している点だ。

MS Projectは、デフォルトではタスクが1行追加される、あるいはデュレーションが変更されるたびに、全体のクリティカルパスや先行・後続タスクのリンクを再評価する。これが数千行に及ぶプロジェクトファイルであればどうなるか? 1回の処理に数分を要する「使い物にならないゴミコード」が完成する。

さらに厄介なのが、プロジェクト全体の設定(オプション)が、ユーザーのPC環境やファイル自体の初期値に依存している点だ。これをコード側で明示的に制御・固定化(イミュータブルに設計)しなければ、環境依存のバグを防ぐことはできない。

—

2. 制御すべき主要な `Application.Options` プロパティ

VBAからプロジェクトの計算エンジンを制御するためには、以下のオプション群を熟知し、処理の目的に応じて動的に切り替える必要がある。

  • `AutoAddNewTasks`: 新規タスクのスケジュール方法(手動か自動か)を強制する。
  • `CalculationMode`: 計算を手動(Manual)にするか自動(Automatic)にするか。
  • `HonorConstraints`: 「できる限り早く(ASAP)」などの制約条件をスケジュールに厳格に適用させるか。
  • `SplitInProgressTasks`: 進行中のタスクの分割を許可するか。

これらを適切にハンドリングすることで、計算エンジンの無駄な暴走を防ぎ、爆発的な処理速度の向上と意図通りのスケジュール計算を実現できる。

—

3. 【実践】堅牢性とパフォーマンスを極めたプロダクションコード

ここに示すのは、実務の現場でそのまま利用できる、トランザクション制御を意識した堅牢なVBAモジュールだ。

処理の開始時に現在の計算モードやオプションの状態を退避(スナップショット)し、処理中は完全な手動計算モード+自動タスク化で高速にオブジェクトを構築。最後に一括で再計算を行い、確実に元の状態へ復元する――これがプロのアーキテクトの作法だ。

Option Explicit

‘ ==============================================================================
‘ モジュール名: ModProjectEngineController
‘ 概要: MS Projectの計算エンジンを制御し、高速かつ意図通りにスケジュールを構築する
‘ ==============================================================================

Public Sub ExecuteRobustScheduleBuilding()
Dim startTime As Double
startTime = Timer

‘ — 1. 状態の退避(環境依存の排除とクリーンアップの担保) —
Dim orgCalculationMode As Long
Dim orgAutoAddNewTasks As Boolean
Dim orgHonorConstraints As Boolean

On Error GoTo ErrorHandler

‘ アプリケーション全体のパフォーマンス設定を一時退避
orgCalculationMode = Application.CalculationMode
orgAutoAddNewTasks = ActiveProject.OptionsAutoAddNewTasks
orgHonorConstraints = ActiveProject.OptionsHonorConstraints

‘ — 2. 計算エンジンのロックと最適化設定 —
‘ 計算モードを「手動」に変更し、余計な再計算を完全にシャットアウト
Application.CalculationMode = pjCalcManual

‘ 新規タスクは常に「自動スケジュール」として生成するよう強制
ActiveProject.OptionsAutoAddNewTasks = True

‘ 制約条件を厳格に遵守させる設定
ActiveProject.OptionsHonorConstraints = True

‘ 画面描画の停止(パフォーマンス劇的向上)
Application.ScreenUpdating False

‘ — 3. コアロジック(高速なタスク・リソースの構築) —
Call BuildProjectStructure

‘ — 4. 変更の確定と強制再計算 —
‘ 計算モードを戻す前に、一度プロジェクト全体を強制再計算させる
Application.CalculationMode = pjCalcAutomatic

‘ 念のためプロジェクト全体の再計算を実行
Calculate

‘ 終了処理
Application.ScreenUpdating True

MsgBox “スケジュール構築が正常に完了しました。(処理時間: ” & Format(Timer – startTime, “0.00”) & “秒)”, vbInformation, “成功”
Exit Sub

ErrorHandler:
‘ — 5. 堅牢なロールバック&クリーンアップ —
Application.ScreenUpdating True

‘ エラーが発生しても必ず元の設定を復元する
Application.CalculationMode = orgCalculationMode
ActiveProject.OptionsAutoAddNewTasks = orgAutoAddNewTasks
ActiveProject.OptionsHonorConstraints = orgHonorConstraints

MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
End Sub

Private Sub BuildProjectStructure()
‘ 【実務用ダミー実装】
‘ 実際にはここでデータベースや外部ファイル(Excel/API)からデータを読み込み、
‘ タスクの追加・リンク設定を行う。

Dim tsk As Task
Dim i As Long

‘ 既存タスクのクリア(必要に応じて)
‘ ActiveProject.Tasks.Clear

‘ 高速バルク処理のシミュレーション(計算エンジンが停止しているため高速)
For i = 1 to 500
Set tsk = ActiveProject.Tasks.Add(Name:=”タスク_” & i)
tsk.Duration = “3d”

‘ 先行タスクの紐付け(例:1つ前のタスクにリンク)
If i > 1 Then
tsk.TaskDependencies.Add From:=ActiveProject.Tasks(i – 1), Type:=pjFinishToStart
End If
Next i

End Sub

—

4. ファイル・データベース連携における致命的な罠と回避策

外部の基幹システムやSQLデータベース、あるいはExcelから取得した工程データをMS Projectに流し込む際、今回の計算エンジン制御と合わせて注意すべきポイントがある。

① 日付フォーマットとカレンダーの不一致

データベースから取得した `Start` 日付をそのまま代入しても、MS Project側の「稼働日カレンダー(休日・営業時間)」の概念とズレている場合、計算エンジンが勝手に日付を「繰り上げ・繰り下げ」する。

  • 対策: 日付を代入する前に、プロジェクトのカレンダー設定が正しく適用されているか確認し、必要であれば `Task.ConstraintType` を明示的に設定(例: `pjConstraintASAP` や `pjConstraintMSO`:指定日必着など)して、エンジン勝手な日付の改変を防ぐ。

② 外部トランザクションとの整合性

データベース側の更新とProjectファイルの保存が非同期に行われると、中途半端な状態でファイルが破損するリスクがある。

  • 対策: VBA内でファイルを操作する場合は必ず「変更フラグ(`ActiveProject.Saved`)」を管理し、エラー発生時にはファイルを上書き保存せずに閉じる(`ActiveProject.Close pjDoNotSave`)鉄の掟をコードに組み込むこと。

—

5. リーダーからの総括

「コードが動けばいい」というフェーズは、個人で趣味のスクリプトを書いている時で終わりだ。組織の基幹業務や、数百人が関わるプロジェクトの工程表を制御するVBAを書くのであれば、ツールの挙動そのものをプログラムで支配する気概が求められる。

今回紹介した `Application.Options` を活用した計算エンジンの制御は、その第一歩であり、最も効果的なアプローチだ。ぜひ君のプロジェクトにもこの設計思想を取り入れ、バグ知らずの堅牢な自動化システムを構築してほしい。

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