Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VBA Async HTTP API Sample

Excel VBAだけで、非同期HTTPクライアントとローカル簡易HTTPサーバーを動かし、通信の両側をTraceIdで追跡する学習用サンプルです。

外部のPowerShell、curl、Webサービス、APIキーは使いません。クライアントとサーバーを自分のPC内で動かすため、HTTPの要求・応答、非同期イベント、エラー処理を段階的に観察できます。

対象: Windows版Excel / VBA7(32ビット版・64ビット版Office)
用途: 初学者、学生、社内研修、VBAからREST APIを呼び出す前の基礎学習
注意: このサーバーは教材です。業務用・公開用Webサーバーとしては使用できません。

何を学べるか

  • 同期通信と非同期通信の違い
  • MSXML2.XMLHTTP60readyStateとイベント駆動
  • HTTPのリクエスト行、ヘッダー、本文、ステータスコード
  • TCPのsocketbindlistenacceptrecvsend
  • VBAのUnicode文字列とHTTPのUTF-8バイト列の違い
  • Content-Lengthが「文字数」ではなく「バイト数」である理由
  • クライアントとサーバーを同じTraceIdで追跡する方法
  • HTTP 500、接続失敗、遅延、キャンセルの観察
  • 秘密情報をトレースへ残さない設計の考え方

全体像

sequenceDiagram
    participant C as Client.xlsm
    participant S as Server.xlsm
    C->>S: HTTP要求 + X-Trace-Id
    Note over C: Send後すぐExcelへ制御を戻す
    S->>S: 解析・ルート処理
    S-->>C: HTTP応答 + 同じX-Trace-Id
    Note over C,S: 両方のTraceシートを照合
Loading

推奨構成は、1冊のマクロブックへ全5モジュールを取り込み、マクロから同じブックを別Excelプロセスで読み取り専用として開く方法です。

Excelプロセス ブック 役割
元のExcel VBA_Async_HTTP_API_Sample.xlsm 非同期クライアントを実行
自動起動したExcel 同じブックの読み取り専用コピー 127.0.0.1:18080で簡易HTTPサーバーを実行

/delay?ms=3000を使うと、サーバー側が約3秒待機している間もクライアント側Excelを操作できます。これが非同期通信を体験する最も分かりやすいサンプルです。

ファイル構成

VBA_Async_HTTP_API_Sample/
├─ README.md
├─ SECURITY.md
├─ src/
│  ├─ CAsyncHttpClient.cls  非同期HTTPクライアント
│  ├─ modClientDemo.bas     クライアント用の実行マクロ
│  ├─ modHttpServer.bas     Winsock簡易HTTPサーバー
│  ├─ modTrace.bas          Traceシートへの共通記録
│  └─ modUtf8.bas           Unicode/UTF-8変換
└─ docs/
   ├─ TESTING.md            テスト手順と期待結果
   └─ REVIEW.md             疑似ペルソナ100回の静的レビュー記録

すぐに試す手順

1. 1冊のマクロブックを作る

  1. Windows版Excelを起動します。
  2. 新しいブックをVBA_Async_HTTP_API_Sample.xlsmとして保存します。
  3. Alt+F11でVBE(Visual Basic Editor)を開きます。
  4. ツール参照設定で、Microsoft XML, v6.0にチェックを付けます。
  5. ファイルファイルのインポートで、次の5ファイルをすべて読み込みます。
    • src/modTrace.bas
    • src/modUtf8.bas
    • src/modHttpServer.bas
    • src/CAsyncHttpClient.cls
    • src/modClientDemo.bas
  6. デバッグVBAProjectのコンパイルを実行します。
  7. ブックを保存します。

2. サーバー用Excelを自動起動する

元のブックでServer_StartInNewExcelを実行します。

このマクロは次を自動で行います。

  1. CreateObject("Excel.Application")で別Excelプロセスを作る。
  2. 保存済みの同じ.xlsmを読み取り専用で開く。
  3. サーバー側のTraceシートを初期化する。
  4. サーバー側コピーでServer_Startを実行する。

Shell、PowerShell、curlは使いません。別のExcelウィンドウが開き、そのTraceシートにLISTEN / READYが表示されれば起動完了です。

マクロを許可できない場所から開いた場合や、組織ポリシーで自動化されたブックのマクロが禁止されている場合は起動できません。セキュリティ設定を回避せず、信頼できる場所と組織の規則を確認してください。

3. 元のブックからクライアントを実行する

元のExcelへ戻り、Client_Helloを実行します。元ブックのTraceシートでREADY_STATEHTTP 200を確認します。

サーバーは127.0.0.1:18080だけで待ち受けます。127.0.0.1はループバックアドレスで、同じPC自身を表します。

4. 終了する

元のブックでServer_StopInNewExcelを実行します。サーバーへ停止を依頼し、読み取り専用コピーを保存せず閉じ、サーバー用Excelプロセスも終了します。

Client_ShutdownServerはHTTPの/shutdownを学ぶためのマクロです。待受けは停止しますが、Traceを観察できるようサーバー用Excelウィンドウは残ります。観察後にServer_StopInNewExcelを実行してください。

手動で2つのブックへ分ける方法も利用できます。その場合は、サーバー用ブックへmodTracemodUtf8modHttpServerを、クライアント用ブックへmodTraceCAsyncHttpClientmodClientDemoを取り込みます。

用意しているエンドポイント

メソッド URL 学習内容 主な応答
GET /hello 最小の要求・応答 HTTP 200 + 固定JSON
POST /echo 本文とContent-Length 送った本文をそのまま返す
GET /delay?ms=3000 非同期と待機 指定時間後にHTTP 200
GET /status/500 HTTPエラー 意図的なHTTP 500
POST /shutdown 後始末 応答後にサーバー停止

msは0~10000ミリ秒に制限しています。数値でない場合は1000ミリ秒になります。

実行用マクロ

マクロ 動作
Client_Hello /helloを呼ぶ
Client_Echo JSONを/echoへPOSTする
Client_Delay3Seconds 3秒遅延を試す
Client_Status500 HTTP 500を観察する
Client_RunBasicSequence 3要求を連続開始する
Client_CancelAll 実行中の要求を中止する
Client_ShutdownServer サーバーを遠隔停止する
Server_StartInNewExcel 同じブックを別Excelプロセスで開き、サーバーを開始する
Server_StopInNewExcel 自動起動したサーバーとExcelプロセスを終了する
Server_Start 待受けを開始する
Server_Stop 待受けとWinsockを終了する
Trace_Clear Traceシートを初期化する

トレースの読み方

Traceシートには次の列を作ります。

意味
日時 ミリ秒付きの記録時刻
TraceId 1つの要求を結び付ける識別子
CLIENTまたはSERVER
処理段階 SENDRECEIVEPARSEなど
方向 OUTINLOCAL
詳細 URL、受信バイト数、応答本文など
結果 OKWAITINGHTTP 500など
経過時間(ms) 要求開始または接続受付からの時間

たとえば/echoでは、概ね次の順番になります。

CLIENT  CREATE       LOCAL  POST /echo
CLIENT  READY_STATE  IN     OPENED
CLIENT  SEND         OUT    本文文字数=...
SERVER  ACCEPT       IN     クライアント接続を受付
SERVER  RECEIVE      IN     受信=...バイト
SERVER  PARSE        LOCAL  POST /echo
SERVER  RESPONSE     OUT    HTTP 200
CLIENT  READY_STATE  IN     HEADERS_RECEIVED
CLIENT  READY_STATE  IN     LOADING
CLIENT  READY_STATE  IN     DONE
CLIENT  TRACE_ID     IN     MATCH
CLIENT  RESPONSE     IN     HTTP 200の本文
CLIENT  COMPLETE     LOCAL  OK

クライアントのX-Trace-Id要求ヘッダーをサーバーが読み、同じ値を応答ヘッダーにも付けます。クライアントは応答値を照合し、TRACE_ID / MATCHを記録します。2冊のTraceシートをTraceIdで絞り込むと、1要求だけを追跡できます。

A~G列は文字列形式、経過時間のH列は数値形式です。値はValue2で書き込み、同じ内容をVBEのイミディエイトウィンドウへもDebug.Printで出力します。

readyStateとは

名前 意味
0 UNSENT まだ初期化されていない
1 OPENED Openが完了した
2 HEADERS_RECEIVED HTTP応答ヘッダーを受信した
3 LOADING 応答本文を受信中
4 DONE 通信処理が完了した

HTTP 500でもreadyStateは4になります。DONEは「HTTP処理の成功」ではなく「通信処理が完了した」という意味です。そのため、完了後にStatusも必ず確認します。

なぜクラスモジュールを使うのか

XMLHTTP60onreadystatechangeを受け取るには、WithEventsをクラスモジュール内で宣言します。

Private WithEvents m_http As MSXML2.XMLHTTP60

さらに、非同期要求を開始したSubが終わってもクラスが破棄されないよう、modClientDemoCollectionへ保持します。完了後はCollectionから取り除きます。

サーバー側の処理順

WSAStartup
  ↓
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  ↓
bind(127.0.0.1:18080)
  ↓
listen
  ↓
accept
  ↓
recv(ヘッダー末尾とContent-Lengthまで)
  ↓
HTTP解析・ルート処理
  ↓
send(全バイトを送るまで繰り返す)
  ↓
closesocket

待受けと受信には非ブロッキングソケットを使い、Application.OnTimeで約1秒ごとに確認します。したがって、この教材の応答時間には最大約1~2秒程度のポーリング待ちが加わる場合があります。

32ビット版・64ビット版Office

  • API宣言にはPtrSafeを付けています。
  • ソケットハンドルにはLongPtrを使っています。
  • バイト数、ポート番号、エラーコードにはLongを使っています。
  • Windows SDKに合わせ、WSADATAのフィールド順を#If Win64 Thenで分けています。

対象はVBA7です。Office 2010以降のWindows版Excelが目安ですが、実際の利用可否はMicrosoft XML 6.0とWindows APIの提供状況にも依存します。

日本語コメントとファイルの文字コード

ソースはGitHub上で読みやすいUTF-8です。一方、VBEの「ファイルのインポート」は、Officeの版やWindowsの言語設定によってUTF-8の日本語コメントを正しく解釈しない場合があります。

文字化けした場合は、次のどちらかで対応してください。

  1. GitHubのRaw表示からコードをコピーし、VBEの新規モジュールへ貼り付ける。
  2. ソースをWindowsの日本語ANSI(CP932 / Shift_JIS)へ変換してからインポートする。

プロシージャ名や変数名はASCIIで統一しているため、コメントが文字化けしても構文への影響を抑えています。ただし日本語文字列リテラルも含むため、コンパイル前に表示を確認してください。

制限事項

  • Windows版Excel専用です。Mac版ExcelではWinsock APIを利用できません。
  • TLS(HTTPS)サーバー機能はありません。通信先はローカルのHTTPだけです。
  • 1接続ずつ処理します。同時多数接続には対応しません。
  • Chunked Transfer Encoding、Keep-Alive、HTTP/2には対応しません。
  • 要求サイズ上限は65536バイトです。
  • /delayはサーバー側Excelプロセスを指定時間だけ停止します。
  • Application.OnTimeのため、高精度な性能測定には使えません。
  • .xlsmは収録していません。VBAソースを自分で取り込む教材形式です。

トラブルシューティング

「ユーザー定義型は定義されていません」

MSXML2.XMLHTTP60の参照設定が不足しています。クライアント用ブックでMicrosoft XML, v6.0を有効にしてください。

bindのWinsockエラー10048

通常は、同じポートを別プロセスが使用中です。既に起動中のServer.xlsmがないか確認し、終了後に再実行してください。

クライアントのStatusが0

HTTP応答を受け取る前に接続が失敗しています。サーバーがLISTEN / READYになっているか、URLとポートが一致しているか確認してください。

応答がすぐに返らない

サーバーは約1秒間隔でポーリングします。教材として処理段階を観察しやすくする構成であり、高速Webサーバーではありません。

マクロが実行できない

ファイルを信頼できる場所へ置き、Windowsのファイルプロパティに「許可する」があれば内容を確認したうえで設定してください。出所が不明なマクロは実行しないでください。

検証状況

ソース構造、API宣言の32/64ビット方針、エンドポイント分岐、秘密情報のマスキング、後始末、READMEとの対応を静的に確認しています。現在の作成環境にはWindows版Excel/VBEがないため、実機でのコンパイルと通信試験は未実施です。

実機確認では、必ずテスト手順に沿ってVBAProjectのコンパイルから始めてください。実機差が見つかった場合は、Officeのビット数、Excelのバージョン、Windowsのバージョン、Traceシート、エラー番号を添えて報告してください。

セキュリティ

ローカル教材であっても、マクロとネットワーク処理には注意が必要です。SECURITY.mdを先に確認してください。

papanda925のネットワーク学習シリーズ

本リポジトリは、Excel VBAからWindowsのネットワーク機能を学ぶ教材シリーズの一つです。HTTPの前段となるTCP/UDP、名前解決を扱うDNS、到達性と経路を調べるPing/Tracerouteも公開しています。

シリーズの一覧と推奨学習順序は、papanda925 GitHubプロフィールを参照してください。技術記事はpapanda925.comで公開しています。

ライセンス

この教材はMIT Licenseで公開しています。学習、授業、社内研修、改変、再配布に利用できます。再利用する場合は、著作権表示とライセンス文を残してください。ソフトウェアは無保証です。

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages