Project VBAの深淵:BI可視化に向けたリソースデータ抽出の最適解
Projectのプロフェッショナルな現場において、標準のレポート機能に満足しているようでは、真のプロジェクト管理とは呼べない。経営層やPMOが求めるのは、Excelの枠を超えたBIツール(Power BIやTableauなど)による動的な分析だ。
しかし、Projectのデータモデルは、リレーショナルデータベースに慣れたエンジニアほど嫌悪感を抱くほどに「非正規化」されている。リソースの稼働状況をBIへ流し込むためのデータパイプラインを、VBAの限界を突破して構築する方法を伝授する。
—
1. データパイプラインの設計思想:多次元からフラットへ
Projectの「リソースの割り当て」データは、そのままではBIツールで扱いにくい。リソース、タスク、期間、コストが複雑に絡み合っているからだ。我々が行うべきは、「Tidy Data(整然データ)」への変換である。
以下のコードは、単にデータを書き出すだけではない。`Application.CalculateAll`の負荷を回避し、メモリを極限まで節約しながら、大規模なプロジェクトファイルから稼働情報をフラットなCSVへと掃き出すためのアーキテクチャだ。
—
2. メモリと速度を最適化する実装パターン
オブジェクトの解放を怠るVBAプログラマは、メモリリークという「時限爆弾」を抱えて生きているようなものだ。Projectのオブジェクトモデルは特に重い。確実に解放し、高速にI/Oを行うための実装例を示す。
‘ ———————————————————
‘ @title ExtractResourceUtilizationToCSV
‘ @description プロジェクトのリソース稼働状況をBI最適化形式でエクスポート
‘ ———————————————————
Sub ExtractResourceUtilizationToCSV()
Dim prj As Project
Dim res As Resource
Dim asn As Assignment
Dim fileNum As Integer
Dim csvPath As String
‘ プロジェクトオブジェクトの明示的指定(外部連携の基本)
Set prj = ActiveProject
csvPath = ThisWorkbook.Path & “\Resource_Utilization_” & Format(Now, “yyyyMMdd”) & “.csv”
‘ I/Oの最適化:FreeFileで競合を回避し、高速なバイナリ書き出しを行う
fileNum = FreeFile
Open csvPath For Output As #fileNum
‘ ヘッダーの書き出し
Print #fileNum, “ResourceName,TaskName,Start,Finish,Work,Cost,Units”
‘ オブジェクトの巡回:不必要なプロパティアクセスを最小化
For Each res In prj.Resources
If Not res Is Nothing Then
For Each asn In res.Assignments
‘ BIで集計しやすいフラットな形式へ
Print #fileNum, “””” & res.Name & “””,””” & _
asn.Task.Name & “””,” & _
Format(asn.Start, “yyyy-mm-dd”) & “,” & _
Format(asn.Finish, “yyyy-mm-dd”) & “,” & _
asn.Work / 60 & “,” & _
asn.Cost & “,” & _
asn.Units
Next asn
End If
Next res
Close #fileNum
‘ 伝説的アーキテクトの戒め:明示的な解放
Set asn = Nothing
Set res = Nothing
Set prj = Nothing
MsgBox “BIインポート用データのエクスポートが完了しました。”, vbInformation
End Sub
—
3. Windows APIによる「フリーズ防止」の極致
大規模なスケジュールを扱う際、VBAの実行中にUIがフリーズし、ユーザーが「強制終了」を試みる事態は避けねばならない。ここで重要になるのが、`DoEvents`の賢明な利用と、Windows APIを用いたプロセス管理だ。
長時間実行される処理であれば、以下のAPIを組み込み、処理の進捗をステータスバーに表示しつつ、OSのメッセージループを適切に制御すべきだ。
‘ Sleep APIによるCPU負荷の抑制
If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Else
Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
End If
‘ 処理ループの中で呼び出し、CPU占有率を適度に下げることで安定性を確保する
‘ DoEvents を過剰に使うと速度が落ちるため、100回に1回程度がベストプラクティス
If i Mod 100 = 0 Then
DoEvents
Sleep 10
End If
—
4. システム間連携の勘所:レガシーとの共存
このVBAで生成されたCSVは、Power BIの「データフロー」や「Power Query」に直接読み込ませる前提で設計している。
- 日付形式の標準化: `yyyy-mm-dd` に統一することで、BIツール側のロケール設定に依存しない安定した日付パースが可能になる。
- 単位の正規化: Projectは内部で「分」で保持しているデータが多い。分析側で計算不要なよう、VBA側で「時間(Work / 60)」へ変換しておくのが、アーキテクトとしての配慮だ。
結論:ツールは「書く」のではなく「構築」するもの
VBAはレガシーと言われるが、Projectの深い階層構造を叩けるのは、依然としてVBA(とCOMインターフェース)の特権だ。ここで紹介した「データパイプライン構築」の考え方は、将来的にPythonやC#へ移行する際にもそのまま移植可能なロジックである。
コードを書くときは、常に「次世代のエンジニアがこのパイプラインをどう引き継ぐか」を考えろ。そして、オブジェクトを使い終わったら、必ず土に還す(`Nothing`を代入する)こと。それが、真に洗練されたエンジニアの嗜みである。
