【テクニカル・上級編】Resource.Notesフィールドを活用したリソース別作業指示書の自動生成ツール – Project VBA解析バイブル

スポンサーリンク

序文:Project VBAという「聖域」の再定義

Microsoft Project(以下、MS Project)を単なるガントチャート作成ツールだと考えているなら、君はまだその真価の1%も引き出せていない。MS Projectは、エンタープライズにおける「リソース最適化エンジン」であり、その心臓部はVBA(Visual Basic for Applications)という、枯れてはいるが極めて強力なインターフェースによって制御される。

現場のシニアエンジニアやシステム管理者が直面するのは、常に「情報の非対称性」だ。PM(プロジェクトマネージャー)の頭の中にある詳細な指示が、リソース(作業員)に正しく伝わらない。この断絶を埋めるために、我々は`Resource.Notes`という、一見地味なプロパティを「動的命令バッファ」へと昇華させる。

本稿では、Project VBAを用いたリソース別作業指示書の自動生成、および外部システム(Outlook)との連携における、メモリ管理とパフォーマンスを極限まで追求した実装を解説する。

—

1. オブジェクトのライフサイクルとCOMの深淵

Project VBAで大規模なリソース(数千人規模)を扱う際、初心者が陥る最大の罠は「オブジェクトの放置」である。VBAはCOM(Component Object Model)をベースとしており、MS Projectのプロセスと外部プロセス(Outlook等)を跨ぐ処理では、参照カウンタの管理を誤るとメモリリークやゴーストプロセスの発生を招く。

拘り:明示的な解放とアーリーバインディング

パフォーマンスを追求するなら、`Object`型によるレイトバインディングを避け、参照設定によるアーリーバインディングを徹底せよ。そして、処理の終端では必ず`Set … = Nothing`を行い、COMスタックを浄化すること。

—

2. 実装:Resource.Notes 駆動型自動通知エンジン

このコードは、特定のリソースに割り当てられたタスクを走査し、その詳細を`Notes`プロパティに集約。最終的に作業指示書としてメール送信する。

Windows APIによる実行速度の計測と最適化

単にループを回すのではない。`QueryPerformanceCounter`を用い、ミリ秒単位でボトルネックを特定する。

Option Explicit

‘ Windows API: 高精度タイマーによるパフォーマンス計測
Private Declare PtrSafe Function QueryPerformanceCounter Lib “kernel32” (lpPerformanceCount As Currency) As Long
Private Declare PtrSafe Function QueryPerformanceFrequency Lib “kernel32″ (lpFrequency As Currency) As Long

”’

”’ リソース別の作業指示書をNotesから生成し、自動通知する
”’

Public Sub GenerateResourceWorkOrders()
Dim pj As Project: Set pj = ActiveProject
Dim res As Resource
Dim asgn As Assignment
Dim startCount As Currency, endCount As Currency, freq As Currency
Dim workDetail As String

QueryPerformanceFrequency freq
QueryPerformanceCounter startCount

On Error GoTo ErrorHandler

‘ 画面更新と自動計算の停止(パフォーマンス最適化の鉄則)
Application.ScreenUpdating = False
Application.Calculation = pjCalculationManual

For Each res In pj.Resources
‘ 空のリソースやコストリソースを除外
If Not res Is Nothing Then
If res.Type = pjResourceTypeWork And res.Assignments.Count > 0 Then

‘ Notesフィールドの初期化と構築
‘ Notesは内部的にRTFを保持する場合があるため、文字列処理には細心の注意を払う
workDetail = “— 自動生成作業指示書 [” & Format(Date, “yyyy/mm/dd”) & “] —” & vbCrLf

For Each asgn In res.Assignments
‘ 完了していないタスクのみを抽出
If asgn.PercentWorkComplete < 100 Then workDetail = workDetail & "Task: " & asgn.TaskName & " (Start: " & asgn.Start & " - End: " & asgn.Finish & ")" & vbCrLf workDetail = workDetail & "備考: " & asgn.Task.Notes & vbCrLf workDetail = workDetail & "-----------------------------------" & vbCrLf End If Next asgn ' Resource.Notesへの書き込み res.Notes = workDetail ' 通知処理へのブリッジ(外部システム連携) Call NotifyResourceViaEmail(res) End If End If Next res QueryPerformanceCounter endCount Debug.Print "Execution Time: " & (endCount - startCount) / freq & " seconds" CleanUp: ' 状態の復元 Application.ScreenUpdating = True Application.Calculation = pjCalculationAutomatic Set res = Nothing Set pj = Nothing Exit Sub ErrorHandler: MsgBox "Runtime Error: " & Err.Description, vbCritical, "System Architect Alert" Resume CleanUp End Sub ---

3. システム間連携:Outlookへのセキュアなインジェクション

リソースへの通知を自動化する際、Outlookのセキュリティプロンプトが障壁となる場合がある。ここでは、Outlookオブジェクトモデルを制御し、信頼されたコンテキストでメールを射出する。

メモリ最適化を意識したメール送信ロジック

多くの開発者は、ループ内でOutlook Applicationオブジェクトを何度も生成する愚を犯す。これはリソースの浪費だ。

Private Sub NotifyResourceViaEmail(ByRef targetRes As Resource)
‘ static変数を利用し、一度生成したインスタンスを再利用する(Singletonパターンの模倣)
Static olApp As Object
Dim olMail As Object

If olApp Is Nothing Then
On Error Resume Next
Set olApp = GetObject(, “Outlook.Application”)
If olApp Is Nothing Then
Set olApp = CreateObject(“Outlook.Application”)
End If
On Error GoTo 0
End If

‘ リソースにメールアドレスが設定されているか確認
If InStr(targetRes.EMailAddress, “@”) > 0 Then
Set olMail = olApp.CreateItem(0) ‘ olMailItem
With olMail
.To = targetRes.EMailAddress
.Subject = “【重要】本日の作業指示書:” & targetRes.Name
.Body = targetRes.Notes
‘ 現場の要件に応じて .Send ではなく .Display を選択する場合もある
.Send
End With
Set olMail = Nothing
End If
End Sub

—

4. 伝説的なチーフアーキテクトの視点:保守と拡張性

Resource.Notes の限界とメタデータ設計

`Resource.Notes` は便利なバッファだが、プレーンテキスト以上の構造化データ(JSONやXML)を格納し始めると、MS ProjectのUI上での視認性が著しく低下する。シニアエンジニアが取るべき戦略は、「Notesはヒューマンリーダブルな最終出力とし、メタデータはCustomFields(Text1〜30等)に隠蔽する」ことだ。

レガシー環境への配慮

いまだに多くの現場で、Project 2016や2019が混在して動いている。VBAコード内で最新の言語機能(例えば、特定のクラスモジュール機能)を多用しすぎると、環境依存のランタイムエラーを引き起こす。このコードで `PtrSafe` を使用しているのは、32bit/64bitの両アーキテクチャを統べるための最低限の作法である。

—

5. 結論:コードに魂を宿らせる

Project VBAを単なる「マクロ」として扱うか、それとも「プロジェクトの神経系」として構築するか。その差は、オブジェクト一つ一つの生存期間に対する執着と、ユーザー(リソース)の手元に届く情報の鮮度に対する責任感に現れる。

今回紹介した`Resource.Notes`の活用は、自動化の第一歩に過ぎない。真のマスターは、ここからプロジェクトの進捗率(PercentComplete)やコスト超過(CostVariance)を監視し、異常値を検知した瞬間にWindows APIを介してダッシュボードを強制更新させるような、攻めのシステムを構築するだろう。

君のコードが、ただ動くだけでなく、プロジェクトという有機体を加速させるエンジンとなることを期待する。

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