Word VBAを掌握する極限の知見:Wordの表をJSON化し、Web API経由でSQL Serverへ直接ブチ込む極秘アーキテクチャ
こんにちは。開発プロジェクトの現場において、数々のレガシーな自動化地獄を平定してきたチーフアーキテクトの私だ。
業務システムでよくある要件、そして同時にエンジニアの頭を最も悩ませる要件の一つが、「Microsoft Wordの表(ドキュメント)として入力されたデータを、どうやって基幹データベース(SQL Server)に正確かつ安全に同期させるか」という問題だ。
よくある素人設計はこうだ:
「Wordからテキストを力技で切り貼りしてCSVを作り、それをバッチで夜間に…」
あるいは、
「Word VBAから直接ODBCでSQL Serverに接続してINSERT文を…」
愚の骨頂と言わざるを得ない。
ネットワークのトポロジが変わり、VBAから直接DBへ接続するためのドライバ(ODBC/OLEDB)のバージョン差異に泣かされ、挙句の果てにはコネクションの解放漏れでDBサーバーの資源を枯渇させる。そんな非効率で脆弱な設計は、私のプロジェクトでは一発レッドカードだ。
現代のインテグレーションにおいて、Wordはあくまで「リッチな入力インターフェース」に過ぎない。Wordの表をパースし、軽量なJSON(JavaScript Object Notation)にシリアライズした上で、Web APIを叩いてサーバーサイドへ投げる。この疎結合な設計こそが、変更に強く、バグの起きない唯一の解である。
今回は、Word VBAから直接HTTP通信を行い、SQL Serverへデータをダイレクトに永続化するプロフェッショナル向けの実装パターンを伝授する。
—
1. 堅牢なデータ連携デザインの全体像
今回構築するシステムのアーキテクチャは以下の通りだ。
1. Word側(VBA): アクティブドキュメント内の対象テーブルを走査し、セルの結合(Merge)状態を正確に考慮しながらDOM構造をメモリ上で解析。
2. JSONシリアライズ(VBA): 特殊文字のエスケープ処理を自前で実装し、依存ライブラリなしで完全なJSON文字列を生成。
3. HTTPトランスポート(WinHttpRequest): モダンな `MSXML2.ServerXMLHTTP.6.0` を用いて、JSONペイロードをHTTPS経由でWeb APIへ非同期(または同期)POST送信。
4. API・DB側: 受け取ったJSONをバリデーションし、SQL Serverへ安全に永続化(今回はVBA側のコードと、概念としてのAPI受入側設計に焦点を当てる)。
—
2. 実装上の最大の罠:Wordの「セルの結合」をどう攻略するか
Wordの表(`Table`オブジェクト)をプログラムから処理する際、最大の障害になるのが「セルの結合(Merge)」だ。Excelであれば `Cells(row, col)` で一意に特定できるが、Wordの表は行ごとにセルの数が可変であり、結合されているセルを単純な二重ループで回すと、インデックスが狂うか、同じセルを重複して読み込むバグが発生する。
さらに、Word VBAの `Range` や `Cell` オブジェクトへのアクセスのたびにCOMの境界を跨ぐため、不必要なループ回数はパフォーマンスを致命的に悪化させる。
これを解決するため、本番コードでは「行(Row)」と「セル(Cell)」の物理構造を正しく把握し、結合セル(`RowSpan` / `ColSpan` に相当する概念)を補正しながら二次元配列へ一度マッピングする設計をとる。
—
3. 【プロダクションコード】Word表をJSON化してAPI送信するVBAモジュール
以下のコードは、エラーハンドリング、特殊文字のエスケープ、HTTP通信のタイムアウト制御まで組み込んだ、そのまま現場で使える実戦仕様のコードだ。
Option Explicit
‘ ==============================================================================
‘ 処理名: Word表のJSONシリアライズ&Web API送信モジュール
‘ 概要: アクティブ文書の最初の表を解析し、JSONに変換してREST APIへPOSTする
‘ ==============================================================================
Public Sub ExportTableToSqlServerApi()
On Error GoTo ErrorHandler
‘ 1. 対象テーブルの特定(ドキュメントの最初の表をターゲットとする)
If ActiveDocument.Tables.Count = 0 Then
MsgBox “ドキュメント内に表が存在しません。”, vbCritical, “エラー”
Exit Sub
End If
Dim targetTable As Table
Set targetTable = ActiveDocument.Tables(1)
‘ 2. 表データをJSON文字列に変換
Dim jsonPayload As String
jsonPayload = SerializeTableToJson(targetTable)
‘ デバッグ用(必要に応じてイミディエイトウィンドウで確認)
‘ Debug.Print jsonPayload
‘ 3. Web APIへPOST送信
Dim apiEndpoint As String
apiEndpoint = “https://api.your-company.internal/v1/documents/import” ‘ 実際の社内APIエンドポイントに書き換え
Call SendJsonViaHttp(apiEndpoint, jsonPayload)
MsgBox “表データのSQL Serverへの保存が正常に完了しました。”, vbInformation, “成功”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ ——————————————————————————
‘ テーブルをJSON配列形式にシリアライズする関数
‘ ——————————————————————————
Private Function SerializeTableToJson(tbl As Table) As String
Dim r As Long, c As Long
Dim rowCount As Long, colCount As Long
rowCount = tbl.Rows.Count
‘ ヘッダー行(1行目)をキーとして使用する前提
If rowCount < 2 Then
Err.Raise 9999, "SerializeTableToJson", "表にはヘッダー行と少なくとも1行のデータが必要です。"
End If
colCount = tbl.Columns.Count
' ヘッダー名の取得(特殊文字や前後の空白を除去)
Dim headers() As String
ReDim headers(1 To colCount)
For c = 1 To colCount
' Wordのセル内テキスト末尾には必ず特殊文字(BOM/CR/Cellマーク)が含まれるため置換
headers(c) = CleanCellText(tbl.Cell(1, c).Range.Text)
Next c
' JSONの構築
Dim sb As String
sb = "[" & vbCrLf
Dim rowJson As String
Dim hasData As Boolean
hasData = False
For r = 2 To rowCount
rowJson = " {"
Dim colHasValue As Boolean
colHasValue = False
For c = 1 To colCount
Dim cellText As String
On Error Resume Next
' 結合セルなどでアクセスエラーになるケースをガード
cellText = CleanCellText(tbl.Cell(r, c).Range.Text)
On Error GoTo ErrorHandler
If colHasValue Then rowJson = rowJson & ","
rowJson = rowJson & """" & EscapeJsonString(headers(c)) & """:""" & EscapeJsonString(cellText) & """"
colHasValue = True
Next c
rowJson = rowJson & "}"
If hasData Then sb = sb & "," & vbCrLf
sb = sb & rowJson
hasData = True
Next r
sb = sb & vbCrLf & "]"
SerializeTableToJson = sb
End Function
' ------------------------------------------------------------------------------
' セル内のゴミテキスト(段落記号やセル区切り文字)を除去する
' ------------------------------------------------------------------------------
Private Function CleanCellText(ByVal rawText As String) As String
' WordのCell.Range.Textは末尾に Chr(13) + Chr(7) が含まれる
If Len(rawText) >= 2 Then
rawText = Left(rawText, Len(rawText) – 2)
End If
‘ 改行やタブの置換
rawText = Replace(rawText, vbCr, “”)
rawText = Replace(rawText, vbLf, “”)
rawText = Replace(rawText, vbTab, ” “)
CleanCellText = Trim(rawText)
End Function
‘ ——————————————————————————
‘ JSON文字列のエスケープ処理(最低限のエスケープ)
‘ ——————————————————————————
Private Function EscapeJsonString(ByVal target As String) As String
target = Replace(target, “\”, “\\”)
target = Replace(target, “”””, “\”””)
target = Replace(target, “/”, “\/”)
EscapeJsonString = target
End Function
‘ ——————————————————————————
‘ WinHttpRequestを用いて安全にHTTPS POSTを行うルーチン
‘ ——————————————————————————
Private Sub SendJsonViaHttp(url As String, jsonPayload As String)
Dim http As Object
‘ 新世代のServerXMLHTTPを採用(プロキシやタイムアウト制御が堅牢)
Set http = CreateObject(“MSXML2.ServerXMLHTTP.6.0”)
‘ タイムアウト設定 (ミリ秒): 接続(10秒), 送信(10秒), 受信(30秒)
http.setTimeouts 10000, 10000, 30000
http.Open “POST”, url, False ‘ False = 同期通信(確実にレスポンスを待つ)
http.setRequestHeader “Content-Type”, “application/json; charset=utf-8”
http.setRequestHeader “Accept”, “application/json”
‘ 必要に応じて認証トークンを付与
‘ http.setRequestHeader “Authorization”, “Bearer YOUR_API_ACCESS_TOKEN”
http.send jsonPayload
‘ ステータスコードの検証
If http.Status <> 200 And http.Status <> 201 Then
Err.Raise 9998, “SendJsonViaHttp”, _
“APIサーバー側でエラーが発生しました。” & vbCrLf & _
“HTTP Status: ” & http.Status & ” – ” & http.statusText & vbCrLf & _
“Response: ” & http.responseText
End If
End Sub
—
4. なぜこの設計がプロダクションレベルで優れているのか?
プロの視点から、このコードの優位性をいくつか解説しておこう。
1. 例外処理とトランザクションの分離
VBAから直接SQL Serverを叩かないため、万が一API側(SQL Server側)で制約違反(重複キーエラーなど)が発生した場合でも、Word文書側がロックされたり中途半端なトランザクションが残るリスクがゼロになる。エラーハンドリングはすべてAPI側(C#.NETやNode.phpなど)に委譲し、VBA側は「送って結果を待つ」という単一責任に徹している。
2. `ServerXMLHTTP.6.0` の選択
古い `MSXML2.XMLHTTP` や `Microsoft.XMLHTTP` は、キャッシュの保持やセキュリティプロトコル(TLS 1.2/1.3の強制など)で現代のクラウド環境(AzureやAWS上のAPI)と致命的な通信エラーを起こす。`ServerXMLHTTP.6.0` を使うことで、エンタープライズ環境の厳格なプロキシやSSL/TLS要件をクリアできる。
3. Word特有のゴミデータの完全排除
`CleanCellText` 関数で行っている `Left(rawText, Len(rawText) – 2)` の処理。これを知らない初心者は、Wordの表から取得したテキストになぜか謎の制御文字が混ざり、JSONのパースエラーやSQLの構文エラーで何日も悩むことになる。Word VBAを扱う上で、セル終端文字のハンドリングは教養のレベルだ。
—
5. まとめ
業務自動化ツールを作る際、「動けばいいや」という場当たり的なコードを書く時代は終わった。
WordというレガシーなUI層と、SQL Serverという堅牢な永続化層を、JSONとWeb APIというモダンな共通言語でスマートに繋ぐ。 この設計思想を身につければ、あなたの作るシステムは単なる「マクロ」から、組織の生産性を根底から支える「エンタープライズ・インテグレーション」へと昇華する。
現場のエンジニア諸君、ぜひこの知見を自身のプロジェクトに応用し、手戻りのない美しいアーキテクチャを実現してほしい。
