【テクニカル・上級編】【初心者向け】ベースライン設定後の進捗率を自動計算して別シートへ出力する仕組み – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:ベースラインから進捗を射抜く「非同期の作法」

Project VBAを扱うことは、単なる自動化ではない。それは、MS Projectという巨大でブラックボックス化したオブジェクトモデルの深淵を覗き込み、その脈動を制御する行為に他ならない。

多くのエンジニアが「Projectの進捗率をExcelに書き出す」というありふれたタスクで躓く。原因は明白だ。オブジェクトのライフサイクルを軽視し、メモリのリークを放置し、そしてMS Project特有の「計算エンジン」の挙動を理解していないからだ。

今日は、ベースライン設定直後のタスク状況をExcelへ高精度に掃き出す、現場のプロが使うべき設計思想を授ける。

1. アーキテクチャの急所:なぜ「直接参照」で死ぬのか

MS Projectのオブジェクトは、一度インスタンス化されると、メモリを強欲に喰らう。特に`Application.Projects`や`Task`オブジェクトをループ内で無造作に走らせると、VBAのガベージコレクションは追いつかず、システムは遅延の沼に沈む。

我々が守るべきは「最小コンテキストの原則」だ。

  • 遅延バインディングの採用: `Early Binding`は開発時は便利だが、配布後の環境差分(バージョン不一致)で即座にクラッシュする。`Late Binding`で柔軟性を担保しつつ、定数を自前で定義する。
  • メモリの明示的解放: `Set obj = Nothing`は儀式ではない。巨大なプロジェクトファイルにおいては、オブジェクトの参照を確実に断つことが安定稼働の唯一の解である。

2. 【実装】ベースラインスナップショット・エンジン

以下のコードは、Projectのデータを抽出し、Excelへ高速転送する。ここでは、COM通信のオーバーヘッドを抑えるために、配列(Array)を用いた一括転送を行っている。

‘ プロジェクトベースライン抽出エンジン
Public Sub ExportBaselineSnapshot()
Dim projApp As Object
Dim proj As Object
Dim tasks As Object
Dim wb As Object, ws As Object
Dim taskData() As Variant
Dim i As Long, taskCount As Long

‘ Late Bindingでインスタンスを生成(エラーハンドリングは必須)
On Error Resume Next
Set projApp = GetObject(, “MSProject.Application”)
If projApp Is Nothing Then MsgBox “Projectが起動していません”: Exit Sub
On Error GoTo 0

Set proj = projApp.ActiveProject
taskCount = proj.Tasks.Count

‘ メモリ最適化:配列へデータを一括格納(セルへの直接アクセスは低速なため厳禁)
ReDim taskData(1 To taskCount, 1 To 4)

For i = 1 To taskCount
If Not proj.Tasks(i) Is Nothing Then
taskData(i, 1) = proj.Tasks(i).Name
taskData(i, 2) = proj.Tasks(i).Start
taskData(i, 3) = proj.Tasks(i).Finish
‘ ベースライン1の進捗を読み取る(MS Projectの深い階層)
taskData(i, 4) = proj.Tasks(i).PercentComplete
End If
Next i

‘ Excel連携:既存インスタンスの利用を想定
Set wb = GetObject(, “Excel.Application”).Workbooks.Add
Set ws = wb.Sheets(1)

‘ 一括出力でI/Oを最小化
ws.Range(“A1:D” & taskCount).Value = taskData

‘ オブジェクトの明示的解放(メモリ管理の極意)
Set ws = Nothing: Set wb = Nothing
Set proj = Nothing: Set projApp = Nothing
End Sub

3. システム管理者への警鐘:なぜ「ベースライン」なのか

なぜわざわざベースラインを読み取るのか? それは、プロジェクトの「正解」がそこにあるからだ。

進捗率(`PercentComplete`)は、プロジェクトが進行するにつれて刻々と変化する「流動的データ」だ。対してベースラインは、承認済みの「静的データ」である。この二つを比較することで、初めて「計画からの乖離(Variance)」が浮かび上がる。

  • Win32 APIの活用: 大規模なプロジェクトでは、`GetSystemMetrics`等を使い、現在実行中のProjectインスタンスが「読み取り専用」か「書き込み権限あり」かを判定し、排他制御を行う必要がある。これを行わない自動化は、いつか必ずロックファイルによるクラッシュを招く。
  • レガシー保守の知恵: 10年前のProject 2010ファイルと最新のProject 365では、内部のXMLスキーマが微妙に異なる。`Task`オブジェクトのプロパティを叩く際は、必ず`If Not obj Is Nothing`のチェックを入れ、存在しないプロパティへのアクセスでスタックするのを防げ。

結論:自動化は「責任」である

君たちが書く数行のVBAは、プロジェクトマネージャーの意思決定を左右する重要なレポートへと変換される。数値を一つ誤るだけで、現場の判断は歪む。

「動けばいい」という考えは、レガシー環境においては罪である。メモリを慈しみ、オブジェクトのライフサイクルを支配し、そしてプロジェクトの構造を理解せよ。それが、Project VBAを真に掌握するということだ。

次回の講義では、APIを用いた「非同期の進捗更新通知システム」について深掘りしよう。基礎を固め、真のエンジニアリングを目指せ。

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