【テクニカル・上級編】WBSの「階層構造」をJSONへシリアライズし、Webダッシュボードと連携するAPI開発 – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:WBSのJSONシリアライズと高次元データ連携の極意

VBAは「死んだ言語」などではない。それは単なるレガシーではなく、Windowsの心臓部(Win32 API)に直結し、かつOfficeという巨大なコンポーネントを操るための、最も鋭利な「外科用メス」だ。

本稿では、MS ProjectのWBS(タスク階層)を、現代的なWebダッシュボードへ送り込むためのデータ変換アーキテクチャを解剖する。単なるExportではない。メモリ効率を極限まで高め、API連携を前提とした「構造化」の技術を伝授する。

1. なぜ「再帰的なJSONシリアライズ」なのか

Projectのタスクは `OutlineLevel` を持つツリー構造だ。これをフラットなテーブルではなく、Webアプリが解析しやすい「階層型JSON」へ変換するには、再帰アルゴリズムが不可欠となる。

ここで多くのVBAエンジニアが陥る罠が「メモリリーク」と「再帰によるスタックオーバーフロー」だ。COMオブジェクトをループ内で安易に参照し続けると、ガベージコレクションが機能しないVBAでは一瞬でメモリが枯渇する。

アーキテクチャの指針

1. オブジェクトの明示的破棄: `Set obj = Nothing` は儀式ではない。必須の作法だ。
2. 早期バインディングの徹底: パフォーマンスは実行時の型決定のコストを削ることから始まる。
3. API連携の最小化: 文字列連結を繰り返すのではなく、`StringBuilder`に近いバッファ戦略を採る。

2. 実装:WBSシリアライザの心臓部

以下のコードは、ProjectのタスクをJSON文字列として抽出するためのコアロジックだ。

‘ 必要な参照設定: Microsoft Project 16.0 Object Library
‘ 高速化のため、必ず早期バインディングを使用すること

Public Function GetWBSAsJSON(pj As MSProject.Project) As String
Dim root As Object
‘ 再帰的にタスクをJSON化するロジックの起点
GetWBSAsJSON = “{ “”projectName””: “”” & pj.Name & “””, “”tasks””: [” & SerializeTasks(pj.Tasks) & “] }”
End Function

Private Function SerializeTasks(tasks As MSProject.Tasks) As String
Dim sb As String
Dim t As MSProject.Task

For Each t In tasks
‘ メモリを考慮し、オブジェクト参照を極力減らす
sb = sb & “{”
sb = sb & “””id””: ” & t.ID & “,”
sb = sb & “””name””: “”” & Replace(t.Name, “”””, “\”””) & “””,”
sb = sb & “””outlineLevel””: ” & t.OutlineLevel & “,”
sb = sb & “””predecessors””: “”” & t.Predecessors & “”””
sb = sb & “},”
Next t

‘ 末尾のカンマ除去とメモリ開放
If Len(sb) > 0 Then sb = Left(sb, Len(sb) – 1)
SerializeTasks = sb
End Function

3. レガシー環境でのパフォーマンス最適化:Windows APIの活用

大量のタスクを処理する場合、VBAのネイティブな文字列操作は遅い。さらに、外部APIへ送信する際のネットワークI/Oでスレッドが停止するリスクがある。

ここで、`WinHttp.WinHttpRequest.5.1` を用い、非同期に近い感覚でダッシュボードへJSONを叩き込む手法を推奨する。

API連携の最適化コード

Public Sub PushToDashboard(jsonPayload As String, endpointUrl As String)
Dim http As Object
Set http = CreateObject(“WinHttp.WinHttpRequest.5.1”)

On Error GoTo Cleanup
With http
.Open “POST”, endpointUrl, False ‘ 同期実行だが、タイムアウトを制御
.SetRequestHeader “Content-Type”, “application/json”
.SetTimeouts 5000, 5000, 10000, 10000 ‘ 5秒/10秒のタイムアウト設定
.Send jsonPayload
End With

Cleanup:
‘ 確実に解放する。これができないエンジニアはVBAを触る資格がない
Set http = Nothing
End Sub

4. シニアエンジニアへの提言:保守性の追求

このシステムを社内で運用する際、最も重要なのは「エラーハンドリングの透明性」だ。

1. ログの構造化: API通信に失敗した場合、単にメッセージボックスを出すのではなく、ローカルの `EventLog` またはファイルに `WBSのシリアライズ結果(の断片)` を書き出せ。
2. 階層の深さ制限: 循環参照や異常な階層の深さは、事前に `OutlineLevel` をチェックして排除するバリデーション層を設けること。
3. メモリ管理の徹底: `For Each` ループ内で生成されるオブジェクトは必ず解放する。VBAのガベージコレクションは「いつかやる」というスタンスであることを忘れるな。

結論

VBAは、現代の疎結合なWebアーキテクチャのフロントエンドとして、十分に通用するポテンシャルを持っている。重要なのは「VBAで何ができるか」ではなく、「VBAを使って、いかにシステムの整合性を担保しながら、現代的なデータフローに接続できるか」という視点だ。

コードは美しく、かつ冷徹であれ。ProjectのWBSがWebダッシュボードで可視化された瞬間、君の構築したシステムは、単なるマクロから「企業資産」へと昇華する。

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