【テクニカル・上級編】Project VBAで発生する「実行時エラー1101」を回避する安全なタスク操作 – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:実行時エラー1101を封殺する「タスク操作」の極意

Project VBA(MS Projectのオブジェクトモデル)を触ったことがある者なら、一度は目にするであろう「実行時エラー 1101」。それは、システムがタスクの整合性を維持しようとして、開発者の不用意な操作を拒絶する「拒絶のサイン」に他ならない。

多くのエンジニアは、エラーが出るたびに `On Error Resume Next` で誤魔化すか、力技でループを回して解決しようとする。だが、それはメモリリークと予期せぬ計算負荷を招く愚策だ。

今日は、Project VBAのライフサイクルを掌握し、WBSの階層構造や依存関係を「外科手術のように」操作するための、極限の設計術を伝授する。

1. エラー 1101の正体:オブジェクトの「生存権」を理解せよ

実行時エラー 1101は、主に「タスクの追加・移動・リンク設定」において、プロジェクトのスケジュールエンジンが再計算(Recalculation)を強制されるタイミングで発生する。

VBAからProjectを操作する場合、オブジェクトは「キャッシュ」された状態でメモリ上に存在する。UI上では単純に見えるタスクの追加も、裏側では以下の処理が連鎖している。
1. `Task` オブジェクトのメモリ確保
2. IDの再割り当てとインデックスの更新
3. WBS階層の再構築と依存関係の整合性チェック

この処理中に、Projectの内部エンジンが「今、その操作は許可できない」と判断した瞬間、1101が投げられる。これを防ぐには、「操作の単位を最小化し、かつエンジンを一時的に停止させる」という作法が不可欠だ。

2. 実行時エラーを未然に防ぐ「ガード句」設計

タスクを操作する前には、必ずオブジェクトの「生存確認」と「状態確認」を行う必要がある。以下は、私が長年現場で磨き上げた、タスク追加のセーフティ実装例だ。

‘ プロフェッショナルなタスク追加の設計パターン
Public Sub SafeAddTask(ByVal taskName As String, Optional ByVal parentTask As Task)
Dim tsk As Task

‘ 1. プロジェクト全体を計算一時停止モードへ
‘ 不要な再計算を抑制し、エラー1101を物理的に防ぐ
Application.Calculation = pjManual

On Error GoTo ErrorHandler

‘ 2. オブジェクト追加のセーフティチェック
If parentTask Is Nothing Then
Set tsk = ActiveProject.Tasks.Add(taskName)
Else
‘ 階層構造への挿入時、親タスクが削除済みでないかを確認
If parentTask.ID > 0 Then
Set tsk = parentTask.OutlineChildren.Add(taskName)
End If
End If

‘ 3. メモリの明示的解放(VBAではNothing代入が基本)
Set tsk = Nothing

GoTo Cleanup

ErrorHandler:
Debug.Print “Error ” & Err.Number & “: ” & Err.Description
‘ ここでログ出力やリトライ処理を実装する

Cleanup:
‘ 4. 必ず計算モードを元に戻す
Application.Calculation = pjAutomatic
End Sub

3. レガシー環境でのメモリ最適化とパフォーマンス管理

Project VBAは、大規模なWBSを扱う際、COM経由のオブジェクトアクセスで激しくメモリを消費する。特に `Task.Dependencies` をループ処理で叩くのは、パフォーマンスの観点から最悪だ。

依存関係設定の「極意」

数千行のタスクに対して依存関係を付与する場合、一つずつ `Link` を作成してはならない。可能であれば、`Task.LinkPredecessors` メソッドを使い、一度の操作で複数の依存関係をコミットする設計を心がけよ。

また、Windows APIを用いてタスクの操作中、Windowsのメッセージキューを一時的に凍結させる手法も有効だ。

‘ Windows APIを用いた UI再描画の抑制
Private Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hwndLock As LongPtr) As Long

Public Sub BatchUpdateTasks()
‘ UI描画を停止して処理速度を向上させる
LockWindowUpdate Application.hWnd

‘ … 高速なタスク更新処理 …

‘ ロックを解除
LockWindowUpdate 0
End Sub

4. 最後に:伝説的アーキテクトからの提言

Project VBAを扱う上で最も重要なのは、「プロジェクトは生き物である」という認識だ。
コードがタスクを操作するたびに、プロジェクトファイル内部では計算エンジンが唸りを上げている。

  • 単一責任の原則: タスクの追加と、依存関係の付与、属性の更新は、可能な限り独立したプロシージャに分割せよ。
  • 整合性の担保: 処理の前後で必ず `Application.Calculation` を管理せよ。
  • エラーハンドリングの徹底: `Resume` を使って無理やり継続するのではなく、エラー発生時に「どのタスクが・なぜ」失敗したかを特定できるログを吐き出すこと。

VBAはレガシーかもしれない。だが、その背後にあるオブジェクトモデルの理解を極めれば、どんな大規模なプロジェクト管理システムよりも強固な自動化基盤を構築できる。

諸君、コードを汚すな。システムに敬意を払い、メモリの深淵をコントロールせよ。それができる者だけが、真のエンジニアと称されるのだ。

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