【実務・中級編】【上級者向け】Project Server/Online環境における、チェックアウト・チェックインのAPI制御とエラーハンドリング – Project VBA解析バイブル

スポンサーリンク

序論:なぜあなたのProject自動化は「不意に」止まるのか

Microsoft Project Online/Server環境におけるVBA開発において、初心者が最も躓き、かつ中級者が最も軽視するのが「プロジェクトのチェックアウト状態の制御」だ。

ローカルのMPPファイルを操作する感覚でコードを書いているなら、今すぐその考えを捨てろ。サーバー環境におけるプロジェクトファイルは、単なる「ファイル」ではない。それはRDBMS(データベース)上のエンティティであり、厳格な排他制御(セマンティック・ロッキング)の下に管理されている。

「実行中にネットワークが瞬断した」「予期せぬ実行エラーでマクロが止まった」――そんな些細なことで、プロジェクトはサーバー上で「チェックアウトされたまま」のゾンビ状態となり、全ユーザーの編集をブロックする。

本記事では、Project VBAのライフサイクルを完全に掌握し、いかなる異常系においても整合性を保つための「自己回復型チェックアウト・チェックイン・パターン」を伝授する。

1. サーバーベースにおける「状態」の設計思想

Project Online/Server環境において、VBAから操作する際に考慮すべきステータスは以下の3つだ。

1. Checked-In(チェックイン済み): 誰も編集していない。VBAが編集するにはまずチェックアウトを要求する必要がある。
2. Checked-Out to Me(自分にチェックアウト済み): 編集権限を持っている。この状態でのみ保存・発行が可能。
3. Checked-Out to Others(他者にチェックアウト済み): 編集不可。読み取り専用で開くことはできるが、無理に書き込もうとすればAPIエラーで沈む。

多くのエンジニアは「開いて、書き換えて、閉じる」という線形なコードを書く。しかし、プロは「現在の状態を問い合わせ、期待する状態へ遷移させ、最後に元の状態をクリーンアップする」というステートマシンを構築する。

2. 堅牢なチェックアウト・チェックインの実装コード

以下に、実務でそのまま利用できるプロダクション・クオリティのコードを示す。このコードの肝は、`Application.FileOpenEx` と `ProjectCheckOut` / `ProjectCheckIn` の組み合わせ、そして例外発生時の「確実な解放処理」にある。

Option Explicit

‘ ===========================================================================
‘ Module: ServerProjectController
‘ Description: Project Server/Online環境における安全なチェックアウト・チェックイン制御
‘ ===========================================================================

Public Sub SafeProjectUpdate()
Dim targetProjectName As String
targetProjectName = “<>YourProjectName” ‘ サーバー上のプロジェクト名は “<> ” プレフィックスが必要

On Error GoTo ErrorHandler

‘ 1. プロジェクトを読み取り専用で開く(まずは状態を確認するため)
‘ FileOpenExのReadOnly引数をTrueにすることで、競合を避けて安全にオープンする
Application.FileOpenEx Name:=targetProjectName, ReadOnly:=True

Dim activeProj As Project
Set activeProj = Application.ActiveProject

‘ 2. チェックアウト状態の判定
‘ 既に誰かにチェックアウトされていないか?
If activeProj.CheckedOutBy = “” Then
‘ チェックアウトされていないので、編集権限を取得
If Not Application.ProjectCheckOut(activeProj.Name) Then
Err.Raise vbObjectError + 1001, , “チェックアウトの取得に失敗しました。”
End If
ElseIf activeProj.CheckedOutBy <> Application.UserName Then
‘ 自分以外がチェックアウトしている
Err.Raise vbObjectError + 1002, , “プロジェクトは ” & activeProj.CheckedOutBy & ” によってチェックアウト中です。”
Else
‘ 既に自分がチェックアウトしている場合はそのまま続行
End If

‘ ———————————————————
‘ 3. メインロジック(ここに必要な業務処理を記述)
‘ 例:ベースラインの設定、タスクの更新など
‘ ———————————————————
Debug.Print “Update processing: ” & activeProj.Name
‘ BaselineSave All:=True, CopyTo:=pjBaseline, …

‘ ———————————————————

‘ 4. 保存と発行(Server環境ではSaveだけでは不十分。Publishが必要)
Application.FileSave
Application.Publish

‘ 5. チェックインして閉じる
Application.ProjectCheckIn Name:=activeProj.Name
Application.FileCloseEx SaveChanges:=pjDoNotSave ‘ CheckIn時に保存されるため、Close時は不要なダイアログを抑制

MsgBox “処理が正常に完了しました。”, vbInformation
Exit Sub

ErrorHandler:
‘ エラーハンドリングの要。どんなエラーが起きても「放置」しない。
Dim errMsg As String
errMsg = “Error ” & Err.Number & “: ” & Err.Description
Debug.Print “Critical Error: ” & errMsg

‘ ロールバック処理:もし自分がチェックアウトしたままなら、強制的にチェックインを試みる
On Error Resume Next ‘ リカバリ中のエラーは無視
If Not activeProj Is Nothing Then
‘ 自分がチェックアウト主である場合のみ、チェックインを試行
If activeProj.CheckedOutBy = Application.UserName Then
Application.ProjectCheckIn Name:=activeProj.Name
End If
Application.FileCloseEx SaveChanges:=pjDoNotSave
End If

MsgBox “エラーが発生したため、処理を中断しプロジェクトを保護しました。” & vbCrLf & errMsg, vbCritical
End Sub

3. チーフアーキテクトが教える「勝負を分ける」ポイント

① `FileOpenEx` の第1引数 `Name` の秘密

Project Server/Online上のプロジェクトを指す場合、ファイル名の先頭に `<> `(不等号のペアと半角スペース)を付与する必要がある。これを忘れると、VBAはローカルパスを探しに行き、実行時エラーを吐く。

② `ProjectCheckOut` の戻り値を利用せよ

`ProjectCheckOut` メソッドは Boolean 型を返す。これは単に「コマンドが実行されたか」ではなく、「権限が奪取できたか」を意味する。ネットワークの遅延や、サーバー側のバリデーションで拒否されるケースを想定し、必ず戻り値を評価すべきだ。

③ 保存(Save)と発行(Publish)の分離

多くの開発者が忘れるのが、`Publish` だ。`FileSave` はあくまで「作業中(Draft)テーブル」への保存であり、これを実行しただけでは、他のユーザー(PWA参照者など)には変更が見えない。
また、`ProjectCheckIn` を行う前に `Publish` を呼ぶのが標準的な作法だ。

④ エラーハンドリングにおける「冪等性(べきとうせい)」の確保

自動化ツールにおける最悪の挙動は、エラーで止まった後に「中途半端な状態でロックが残る」ことだ。
上記の `ErrorHandler` セクションを見てほしい。`On Error Resume Next` を使いつつ、「自分がロックしている場合のみチェックインを試みる」というガードコードを入れている。これにより、他人の作業を誤って上書きしたり、自分のロックをサーバーに残したりするリスクを最小限に抑えている。

4. パフォーマンスとスケーラビリティの考慮

Project OnlineはREST API(OData)をバックエンドに持っているが、VBAからの操作は依然として重いCOMインターフェースを介する。大量のプロジェクトを一括処理する場合、以下の点に留意せよ。

  • ScreenUpdating の抑制: `Application.ScreenUpdating = False` は基本だが、Projectの場合は描画負荷がExcelより遥かに高い。
  • 計算モードの制御: `Application.Calculation = pjManual` に設定し、すべての更新が終わった後に一括計算させることで、一秒あたりのスループットが劇的に改善する。

結論:Project VBAを「掌握」するということ

Project Server/Onlineの自動化は、単なるマクロの記述ではない。サーバーとの「対話」であり、状態の「管理」である。

今回紹介したチェックアウト・チェックインの制御パターンは、堅牢なシステムの骨組みとなる。APIの仕様を表面なぞるのではなく、その背後にある排他制御の論理を理解したコードを書くこと。それが、現場の混乱を防ぎ、真に価値のある業務自動化ツールを生み出す唯一の道である。

このコードをベースに、あなたのプロジェクト管理を「手動の苦行」から「洗練された自動化」へと昇華させてほしい。

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