VBA

VBAでWinHTTPを利用した非同期通信の実装:詳細な解説と活用方法

VBAはExcelやその他のMicrosoft Officeアプリケーションで使用されるプログラミング言語で、特にデータの通信や処理において優れた機能を発揮します。この記事では、VBAでWinHTTPを使用して非同期通信を行う方法に焦点を当て、その詳細な解説と活用方法について掘り下げていきます。WinHTTPを用いた非同期通信は、リアルタイムなデータ処理やウェブサービスとの連携など、多岐にわたるシナリオで有用です。コードの一部を例に挙げながら、具体的な実装方法を紹介していきます。

今回の内容はVBAの上級者向けの内容となっています。

基本的な実装

VBAでの基本的なソケット通信コードにエラーハンドリングと非同期通信を追加したサンプルです。このサンプルはWinsockではなくWinHTTPを使用して非同期通信を実現しています。エラーハンドリングや非同期通信には適切な機能を追加することが必要です。

Option Explicit

' WinHTTP 非同期通信用の関数宣言
Declare PtrSafe Function WinHttpOpen Lib "winhttp.dll" (ByVal pwszUserAgent As Long, ByVal dwAccessType As Long, ByVal pwszProxyName As Long, ByVal pwszProxyBypass As Long, ByVal dwFlags As Long) As Long
Declare PtrSafe Function WinHttpConnect Lib "winhttp.dll" (ByVal hInternet As Long, ByVal pswzServerName As Long, ByVal nServerPort As Integer, ByVal dwReserved As Long) As Long
Declare PtrSafe Function WinHttpOpenRequest Lib "winhttp.dll" (ByVal hConnect As Long, ByVal pwszVerb As Long, ByVal pwszObjectName As Long, ByVal pwszVersion As Long, ByVal pwszReferrer As Long, ByVal ppwszAcceptTypes As Long, ByVal dwFlags As Long) As Long
Declare PtrSafe Function WinHttpSendRequest Lib "winhttp.dll" (ByVal hRequest As Long, ByVal pwszHeaders As Long, ByVal dwHeadersLength As Long, ByVal lpOptional As Long, ByVal dwOptionalLength As Long, ByVal dwTotalLength As Long, ByVal dwContext As Long) As Long
Declare PtrSafe Function WinHttpReceiveResponse Lib "winhttp.dll" (ByVal hRequest As Long, ByVal lpReserved As Long) As Long
Declare PtrSafe Function WinHttpReadData Lib "winhttp.dll" (ByVal hRequest As Long, ByRef lpBuffer As Any, ByVal dwNumberOfBytesToRead As Long, ByRef lpdwNumberOfBytesRead As Long) As Long
Declare PtrSafe Function WinHttpCloseHandle Lib "winhttp.dll" (ByVal hObject As Long) As Long

' WinHTTP 非同期通信のためのコールバック関数宣言
Declare PtrSafe Function InternetSetStatusCallback Lib "wininet.dll" (ByVal hInternet As Long, ByVal lpfnInternetCallback As Long) As Long
Declare PtrSafe Function WinHttpSetStatusCallback Lib "winhttp.dll" (ByVal hInternet As Long, ByVal lpfnInternetCallback As Long, ByVal dwNotificationFlags As Long, ByVal dwReserved As Long) As Long

' 非同期通信のコールバック関数
Function WinHTTPCallback(ByVal hInternet As Long, ByVal dwContext As Long, ByVal dwInternetStatus As Long, ByVal lpvStatusInformation As Long, ByVal dwStatusInformationLength As Long) As Long
    ' イベントハンドリングなどの処理を追加する
    ' この例では特に何も処理しない
    WinHTTPCallback = 0
End Function

Sub AsyncHTTPRequest()
    Dim hInternet As Long
    Dim hConnect As Long
    Dim hRequest As Long
    Dim sServer As String
    Dim sPath As String
    Dim dwBytesRead As Long
    Dim sBuffer As String

    ' サーバーとパスを設定
    sServer = "www.example.com"
    sPath = "/path/to/resource"

    ' WinHTTP セッションを開く
    hInternet = WinHttpOpen(StrPtr("VBA WinHTTP Example"), 0, 0, 0, 0)

    ' インターネットコールバック関数を設定
    InternetSetStatusCallback hInternet, AddressOf WinHTTPCallback

    If hInternet Then
        ' サーバーに接続
        hConnect = WinHttpConnect(hInternet, StrPtr(sServer), 80, 0)

        If hConnect Then
            ' リクエストを開く
            hRequest = WinHttpOpenRequest(hConnect, StrPtr("GET"), StrPtr(sPath), 0, 0, 0, 0)

            If hRequest Then
                ' リクエストを送信
                If WinHttpSendRequest(hRequest, 0, 0, 0, 0, 0, 0) Then
                    ' レスポンスを受信
                    If WinHttpReceiveResponse(hRequest, 0) Then
                        ' データを読み取る
                        Do
                            sBuffer = String(4096, 0)
                            If WinHttpReadData(hRequest, ByVal StrPtr(sBuffer), Len(sBuffer), dwBytesRead) Then
                                If dwBytesRead > 0 Then
                                    ' ここで受信したデータに対する処理を行う
                                    Debug.Print Left(sBuffer, dwBytesRead)
                                End If
                            End If
                        Loop While dwBytesRead > 0
                    End If
                End If
                ' ハンドルを閉じる
                WinHttpCloseHandle hRequest
            End If
            WinHttpCloseHandle hConnect
        End If
        ' セッションを閉じる
        WinHttpCloseHandle hInternet
    End If
End Sub

このコードは非同期通信を実現するためにWinHTTPを使用しています。WinHTTPはVBAに標準で含まれているため、追加のライブラリのインストールは不要です。非同期通信はイベント駆動型で、WinHTTPCallback関数が通信状態の変化をハンドリングします。

解説

先ほどのコードを分解して解説します。

ライブラリの宣言

WinHTTPを使用するために必要な関数や型を宣言しています。これには非同期通信のコールバック関数も含まれます。

Declare PtrSafe Function WinHttpOpen Lib "winhttp.dll" (ByVal pwszUserAgent As Long, ByVal dwAccessType As Long, ByVal pwszProxyName As Long, ByVal pwszProxyBypass As Long, ByVal dwFlags As Long) As Long
...
Declare PtrSafe Function InternetSetStatusCallback Lib "wininet.dll" (ByVal hInternet As Long, ByVal lpfnInternetCallback As Long) As Long
Declare PtrSafe Function WinHttpSetStatusCallback Lib "winhttp.dll" (ByVal hInternet As Long, ByVal lpfnInternetCallback As Long, ByVal dwNotificationFlags As Long, ByVal dwReserved As Long) As Long

セッションの開始

WinHttpOpen関数を使用してWinHTTPセッションを開始します。ここではユーザーエージェントの指定やプロキシの設定は省略されています。

hInternet = WinHttpOpen(StrPtr("VBA WinHTTP Example"), 0, 0, 0, 0)

インターネットコールバック関数の設定

非同期通信でのイベントを捕捉するために、InternetSetStatusCallback関数を使用してコールバック関数を設定します。

InternetSetStatusCallback hInternet, AddressOf WinHTTPCallback

サーバーへの接続

WinHttpConnect関数を使用して指定したサーバーに接続します。

hConnect = WinHttpConnect(hInternet, StrPtr(sServer), 80, 0)

リクエストの開始

WinHttpOpenRequest関数を使用してHTTPリクエストを開始します。ここではGETメソッドを使用しています。

hRequest = WinHttpOpenRequest(hConnect, StrPtr("GET"), StrPtr(sPath), 0, 0, 0, 0)

リクエストの送信

WinHttpSendRequest関数を使用してリクエストを送信します。この段階ではまだ非同期通信は始まっていません。

WinHttpSendRequest hRequest, 0, 0, 0, 0, 0, 0

レスポンスの受信

WinHttpReceiveResponse関数を使用してサーバーからのレスポンスを待ちます。

WinHttpReceiveResponse hRequest, 0

データの読み取り

WinHttpReadData関数を使用してデータを非同期に読み取ります。これはループ内で継続的に行います。

WinHttpReadData hRequest, ByVal StrPtr(sBuffer), Len(sBuffer), dwBytesRead

ハンドルのクローズ

通信が終了したら、WinHttpCloseHandle関数を使用して各ハンドルをクローズします。

WinHttpCloseHandle hRequest
WinHttpCloseHandle hConnect
WinHttpCloseHandle hInternet

このサンプルは非同期通信を実現するための基本的な構造を示していますが、実際のアプリケーションにはエラーハンドリングや通信の進捗状況を取得するための詳細な実装が必要です。特にコールバック関数 WinHTTPCallback 内でのイベント処理が拡充されることで、通信の進捗やエラー処理をより具体的に行えるので次にそちらの実装を紹介します。

応用サンプル

ファイルのアップロード、フォームデータの送信、基本的な認証(Basic認証)を組み込んだVBAのWinHTTP通信のサンプルコードを紹介します。

Option Explicit

Public Const WINHTTP_AUTH_TARGET_SERVER = 0
Public Const WINHTTP_AUTH_SCHEME_BASIC = 1
Public Const WINHTTP_FLAG_SECURE = &H8000000

Public Declare PtrSafe Function WinHttpOpen Lib "winhttp.dll" _
    (ByVal pwszUserAgent As Long, _
    ByVal dwAccessType As Long, _
    ByVal pwszProxyName As Long, _
    ByVal pwszProxyBypass As Long, _
    ByVal dwFlags As Long) As Long

Public Declare PtrSafe Function WinHttpConnect Lib "winhttp.dll" _
    (ByVal hInternet As Long, _
    ByVal pswszServerName As Long, _
    ByVal nServerPort As Integer, _
    ByVal dwReserved As Long) As Long

Public Declare PtrSafe Function WinHttpOpenRequest Lib "winhttp.dll" _
    (ByVal hConnect As Long, _
    ByVal pwszVerb As Long, _
    ByVal pwszObjectName As Long, _
    ByVal pwszVersion As Long, _
    ByVal pwszReferrer As Long, _
    ByVal ppwszAcceptTypes As Long, _
    ByVal dwFlags As Long) As Long

Public Declare PtrSafe Function WinHttpSendRequest Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal pwszHeaders As Long, _
    ByVal dwHeadersLength As Long, _
    ByVal lpOptional As Long, _
    ByVal lOptionalLength As Long, _
    ByVal lTotalLength As Long, _
    ByVal dwContext As Long) As Boolean

Public Declare PtrSafe Function WinHttpWriteData Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal lpBuffer As Long, _
    ByVal dwNumberOfBytesToWrite As Long, _
    ByRef lNumberOfBytesWritten As Long) As Boolean

Public Declare PtrSafe Function WinHttpReceiveResponse Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal lpReserved As Long) As Boolean

Public Declare PtrSafe Function WinHttpCloseHandle Lib "winhttp.dll" _
    (ByVal hObject As Long) As Boolean

Public Declare PtrSafe Function WinHttpSetCredentials Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal authTargets As Long, _
    ByVal authScheme As Long, _
    ByVal pwszUserName As Long, _
    ByVal pwszPassword As Long, _
    ByVal pAuthParams As Long) As Boolean

Public Declare PtrSafe Function WinHttpQueryDataAvailable Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByRef lpdwNumberOfBytesAvailable As Long) As Boolean

Public Declare PtrSafe Function WinHttpReadData Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal lpBuffer As Long, _
    ByVal dwNumberOfBytesToRead As Long, _
    ByRef lpdwNumberOfBytesRead As Long) As Boolean

Public Declare PtrSafe Function WinHttpAddRequestHeaders Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal pwszHeaders As Long, _
    ByVal dwHeadersLength As Long, _
    ByVal dwModifiers As Long) As Boolean

Public Declare PtrSafe Function WinHttpQueryOption Lib "winhttp.dll" _
    (ByVal hInternet As Long, _
    ByVal dwOption As Long, _
    ByRef lpBuffer As Any, _
    ByRef lpdwBufferLength As Long) As Boolean

Public Declare PtrSafe Function WinHttpSetOption Lib "winhttp.dll" _
    (ByVal hInternet As Long, _
    ByVal dwOption As Long, _
    ByRef lpBuffer As Any, _
    ByVal dwBufferLength As Long) As Boolean

Public Declare PtrSafe Function WinHttpQueryHeaders Lib "winhttp.dll" _
    (ByVal hRequest As Long, _
    ByVal dwInfoLevel As Long, _
    ByVal pwszName As Long, _
    ByRef lpBuffer As Any, _
    ByRef lpdwBufferLength As Long, _
    ByRef lpdwIndex As Long) As Boolean

Public Declare PtrSafe Function WinHttpCrackUrl Lib "winhttp.dll" _
    (ByVal pwszUrl As Long, _
    ByVal dwUrlLength As Long, _
    ByVal dwFlags As Long, _
    ByRef lpUrlComponents As Any) As Boolean

Public Declare PtrSafe Function WinHttpGetProxyForUrl Lib "winhttp.dll" _
    (ByVal hSession As Long, _
    ByVal lpszUrl As Long, _
    ByRef pAutoProxyOptions As AutoProxyOptions, _
    ByRef lppProxyInfo As ProxyInfo) As Boolean

Public Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
    (ByRef dest As Any, ByRef source As Any, ByVal bytes As Long)

Public Declare PtrSafe Function GlobalAlloc Lib "kernel32.dll" _
    (ByVal wFlags As Long, ByVal dwBytes As Long) As Long

Public Declare PtrSafe Function GlobalFree Lib "kernel32.dll" _
    (ByVal hMem As Long) As Long

Public Declare PtrSafe Function GlobalLock Lib "kernel32.dll" _
    (ByVal hMem As Long) As Long

Public Declare PtrSafe Function GlobalUnlock Lib "kernel32.dll" _
    (ByVal hMem As Long) As Long

Public Type AutoProxyOptions
    dwFlags As Long
    dwAutoDetectFlags As Long
    lpszAutoConfigUrl As Long
    lpszProxy As Long
    lpszProxyBypass As Long
End Type

Public Type ProxyInfo
    dwAccessType As Long
    lpszProxy As Long
    lpszProxyBypass As Long
End Type

' バッファの最大サイズ
Public Const MAX_BUFFER_LENGTH As Long = 1024

' HTTPリクエストのContent-Type
Public Const CONTENT_TYPE_FORM As String = "Content-Type: application/x-www-form-urlencoded"
Public Const CONTENT_TYPE_JSON As String = "Content-Type: application/json"

' HTTPリクエストのContent-Disposition
Public Const CONTENT_DISPOSITION_FORM As String = "Content-Disposition: form-data; name="""
Public Const CONTENT_DISPOSITION_FILENAME As String = "filename="""

' WinHTTPのオプション
Public Const WINHTTP_OPTION_USERNAME As Long = 0
Public Const WINHTTP_OPTION_PASSWORD As Long = 1
Public Const WINHTTP_OPTION_PROXY As Long = 38
Public Const WINHTTP_OPTION_PROXY_USERNAME As Long = 43
Public Const WINHTTP_OPTION_PROXY_PASSWORD As Long = 44

' バッファの使用を示す定数
Public Const WINHTTP_NO_PROXY_BYPASS As String = "WINHTTP_NO_PROXY_BYPASS"
Public Const WINHTTP_NO_PROXY_NAME As String = "WINHTTP_NO_PROXY_NAME"
Public Const WINHTTP_NO_PROXY_PORT As Long = -1

' リクエスト用のデータ型
Public Type WINHTTP_PROXY_INFO
    dwAccessType As Long
    lpszProxy As Long
    lpszProxyBypass As Long
End Type

' URLの構成情報を保持するデータ型
Public Type URL_COMPONENTS
    dwStructSize As Long
    lpszScheme As Long
    dwSchemeLength As Long
    nScheme As Long
    lpszHostName As Long
    dwHostNameLength As Long
    nPort As Long
    lpszUserName As Long
    dwUserNameLength As Long
    lpszPassword As Long
    dwPasswordLength As Long
    lpszUrlPath As Long
    dwUrlPathLength As Long
    lpszExtraInfo As Long
    dwExtraInfoLength As Long
End Type

' HTTPリクエストのエラーコード
Public Const ERROR_WINHTTP_TIMEOUT As Long = 12002
Public Const ERROR_WINHTTP_CANNOT_CONNECT As Long = 12029
Public Const ERROR_WINHTTP_CONNECTION_ERROR As Long = 12030
Public Const ERROR_WINHTTP_RESEND_REQUEST As Long = 12032
Public Const ERROR_WINHTTP_INVALID_SERVER_RESPONSE As Long = 12152
Public Const ERROR_WINHTTP_INVALID_HEADER As Long = 12153
Public Const ERROR_WINHTTP_UNKNOWN_OPTION As Long = 12195

' HTTPリクエストの成功コード
Public Const HTTP_STATUS_OK As Long = 200
Public Const HTTP_STATUS_CREATED As Long = 201
Public Const HTTP_STATUS_ACCEPTED As Long = 202
Public Const HTTP_STATUS_NO_CONTENT As Long = 204

' システムエラー
Public Const ERROR_INVALID_PARAMETER As Long = 87
Public Const ERROR_INSUFFICIENT_BUFFER As Long = 122

' メソッドのタイプ
Public Enum HttpRequestMethod
    HttpGet
    HttpPost
End Enum

' HTTPリクエストのオプション
Public Enum HttpRequestOption
    AutoRedirect = 6
    EnableRedirects = 6
    DisableRedirects = 0
    EnableSsl = 4
    DisableSsl = 0
    EnableSecureProtocols = 2212
    DisableSecureProtocols = 0
    EnableTrailingHeaders = 61
    DisableTrailingHeaders = 0
    EnableCookieHeaders = 74
    DisableCookieHeaders = 0
End Enum

' HTTPリクエストのContent-Type
Public Enum HttpRequestContentType
    FormUrlEncoded
    Json
    MultipartFormData
End Enum

' HTTPリクエストのContent-Disposition
Public Enum HttpRequestContentDisposition
    FormData
    File
End Enum

' HTTPリクエストのオプションのフラグ
Public Enum HttpRequestOptionFlag
    Enable = 1
    Disable = 0
End Enum

' HTTPリクエストのヘッダータイプ
Public Enum HttpRequestHeaderType
    HttpRequestHeaderTypeUnknown = 0
    HttpRequestHeaderTypeRequest = 1
    HttpRequestHeaderTypeResponse = 2
End Enum

' HTTPリクエストのヘッダーオプション
Public Enum HttpRequestHeaderOption
    Add
    Replace
End Enum

' HTTPリクエストのContent-Dispositionオプション
Public Enum HttpRequestContentDispositionOption
    FormDataName
    FileName
End Enum

' HTTPリクエストのContent-Dispositionフラグ
Public Enum HttpRequestContentDispositionFlag
    IncludeQuotes
    ExcludeQuotes
End Enum

' イベント種別
Public Enum WinHTTPOptionEventType
    None
    ResolveName
    Connect
    SendRequest
    ReceiveResponse
    WriteComplete
    ReadComplete
    HandleClosing
    HandleClosed
End Enum

' WinHTTPの状態
Public Enum WinHTTPState
    WinHTTPStateRequestNotSent
    WinHTTPStateWaitingForResponse
    WinHTTPStateReceivingResponse
    WinHTTPStateResponseReceived
    WinHTTPStateRequestSent
    WinHTTPStateWritingToRequest
    WinHTTPStateReadingFromResponse
End Enum

' イベントデータ
Public Type WinHTTPOptionEventData
    EventType As WinHTTPOptionEventType
    ErrorCode As Long
    BytesTransferred As Long
    BytesTotal As Long
End Type

' WinHTTPイベントハンドラ
Public Delegate Sub WinHTTPOptionEventHandler(ByVal EventData As WinHTTPOptionEventData)

' WinHTTPリクエストデータ
Public Type WinHTTPRequestData
    hConnect As Long
    hRequest As Long
    Async As Boolean
    hWinHTTPOptionEvent As Long
    AsyncCallback As WinHTTPOptionEventHandler
    IsClosed As Boolean
    HttpRequestMethod As HttpRequestMethod
    Url As String
    Headers As Collection
    RequestData As String
    RequestDataType As HttpRequestContentType
    RequestContentDisposition As HttpRequestContentDisposition
    RequestContentDispositionOption As HttpRequestContentDispositionOption
    RequestContentDispositionFlag As HttpRequestContentDispositionFlag
    ResponseHeaders As String
    ResponseData As String
    ResponseDataType As HttpRequestContentType
    State As WinHTTPState
    OptionType As HttpRequestOption
    OptionFlag As HttpRequestOptionFlag
End Type

' グローバル変数
Public Requests As Collection

' クラスの初期化
Public Sub InitializeClass()
    If Requests Is Nothing Then
        Set Requests = New Collection
    End If
End Sub

' WinHTTPの初期化
Public Function WinHTTPInitialize() As Boolean
    Dim Result As Boolean
    Result = WinHttpOpen("VBA WinHTTP", 0, vbNullString, vbNullString, 0)
    WinHTTPInitialize = Result
End Function

' WinHTTPの終了
Public Function WinHTTPClose() As Boolean
    Dim Result As Boolean
    Result = WinHttpCloseHandle(0)
    WinHTTPClose = Result
End Function

' WinHTTPリクエストの初期化
Public Function InitializeWinHTTPRequest(Optional ByVal Async As Boolean = False, Optional ByVal AsyncCallback As WinHTTPOptionEventHandler = Nothing) As WinHTTPRequestData
    Dim RequestData As WinHTTPRequestData
    RequestData.Async = Async
    RequestData.AsyncCallback = AsyncCallback
    RequestData.IsClosed = False
    RequestData.Headers = New Collection
    Set InitializeWinHTTPRequest = RequestData
End Function

' WinHTTPリクエストの終了
Public Sub CloseWinHTTPRequest(ByRef RequestData As WinHTTPRequestData)
    If RequestData.Async Then
        RequestData.IsClosed = True
        ' WinHTTPの非同期イベント用のリクエストをクローズ
        WinHttpCloseHandle RequestData.hWinHTTPOptionEvent
    Else
        ' WinHTTPの同期リクエストをクローズ
        CloseWinHTTPRequestSync RequestData
    End If
    Set RequestData.Headers = Nothing
    Set RequestData = Nothing
End Sub

' WinHTTP同期リクエストの終了
Public Sub CloseWinHTTPRequestSync(ByRef RequestData As WinHTTPRequestData)
    ' WinHTTPのリクエストをクローズ
    WinHttpCloseHandle RequestData.hRequest
    ' WinHTTPの接続をクローズ
    WinHttpCloseHandle RequestData.hConnect
End Sub

' WinHTTPリクエストヘッダーの追加/置換
Public Sub AddReplaceWinHTTPRequestHeader(ByRef RequestData As WinHTTPRequestData, ByVal HeaderName As String, ByVal HeaderValue As String, Optional ByVal Option As HttpRequestHeaderOption = Add)
    Dim Header As String
    Header = HeaderName & ": " & HeaderValue
    If Option = Add Then
        RequestData.Headers.Add Header
    ElseIf Option = Replace Then
        ' 既存のヘッダーを置換
        Dim i As Integer
        For i = 1 To RequestData.Headers.Count
            If InStr(RequestData.Headers(i), HeaderName & ":") = 1 Then
                RequestData.Headers(i) = Header
                Exit Sub
            End If
        Next i
        ' 該当するヘッダーが見つからなかった場合は新しく追加
        RequestData.Headers.Add Header
    End If
End Sub

' WinHTTPリクエストのヘッダーを設定
Public Sub SetWinHTTPRequestHeaders(ByRef RequestData As WinHTTPRequestData, ByVal hRequest As Long)
    Dim Header As Variant
    For Each Header In RequestData.Headers
        WinHttpAddRequestHeaders hRequest, StrPtr(Header), -1, WINHTTP_ADDREQ_FLAG_ADD
    Next Header
End Sub

' WinHTTPリクエストデータの設定
Public Sub SetWinHTTPRequestData(ByRef RequestData As WinHTTPRequestData, ByVal hRequest As Long)
    If RequestData.RequestData <> "" Then
        Dim Data As String
        Data = RequestData.RequestData
        WinHttpSendRequest hRequest, StrPtr(CONTENT_TYPE_FORM), -1, StrPtr(Data), Len(Data), Len(Data), 0
        WinHttpWriteData hRequest, StrPtr(Data), Len(Data), 0
    End If
End Sub

' WinHTTPリクエストのContent-Typeを設定
Public Sub SetWinHTTPRequestContentType(ByRef RequestData As WinHTTPRequestData, ByVal hRequest As Long)
    Dim ContentType As String
    Select Case RequestData.RequestDataType
        Case FormUrlEncoded
            ContentType = CONTENT_TYPE_FORM
        Case Json
            ContentType = CONTENT_TYPE_JSON
        Case MultipartFormData
            ContentType = "Content-Type: multipart/form-data; boundary=" & Chr(34) & "---------------------------" & Mid(CreateObject("Scriptlet.TypeLib").GUID, 2, 36) & Chr(34)
    End Select
    WinHttpAddRequestHeaders hRequest, StrPtr(ContentType), -1, WINHTTP_ADDREQ_FLAG_REPLACE
End Sub

' WinHTTPリクエストのContent-Dispositionを設定
Public Sub SetWinHTTPRequestContentDisposition(ByRef RequestData As WinHTTPRequestData, ByVal hRequest As Long)
    Dim ContentDisposition As String
    Select Case RequestData.RequestContentDisposition
        Case FormData
            ContentDisposition = CONTENT_DISPOSITION_FORM & RequestData.RequestContentDispositionOption & Chr(34)
        Case File
            ContentDisposition = CONTENT_DISPOSITION_FILENAME & RequestData.RequestContentDispositionOption & Chr(34)
    End Select
    If RequestData.RequestContentDispositionFlag = ExcludeQuotes Then
        ContentDisposition = Replace(ContentDisposition, Chr(34), "")
    End If
    WinHttpAddRequestHeaders hRequest, StrPtr(ContentDisposition), -1, WINHTTP_ADDREQ_FLAG_ADD
End Sub

' WinHTTPリクエストのURLを設定
Public Function SetWinHTTPRequestURL(ByRef RequestData As WinHTTPRequestData) As Boolean
    Dim UrlComponents As URL_COMPONENTS
    Dim Scheme As String
    Dim HostName As String
    Dim Port As String
    Dim UserName As String
    Dim Password As String
    Dim UrlPath As String
    Dim ExtraInfo As String
    Dim FullURL As String
    Dim Result As Boolean

    Scheme = ""
    HostName = ""
    Port = ""
    UserName = ""
    Password = ""
    UrlPath = ""
    ExtraInfo = ""

    ' URLを構成する各要素を設定
    UrlComponents.dwStructSize = Len(UrlComponents)
    UrlComponents.lpszScheme = StrPtr(Scheme)
    UrlComponents.dwSchemeLength = 0
    UrlComponents.lpszHostName = StrPtr(HostName)
    UrlComponents.dwHostNameLength = 0
    UrlComponents.nPort = 0
    UrlComponents.lpszUserName = StrPtr(UserName)
    UrlComponents.dwUserNameLength = 0
    UrlComponents.lpszPassword = StrPtr(Password)
    UrlComponents.dwPasswordLength = 0
    UrlComponents.lpszUrlPath = StrPtr(UrlPath)
    UrlComponents.dwUrlPathLength = 0
    UrlComponents.lpszExtraInfo = StrPtr(ExtraInfo)
    UrlComponents.dwExtraInfoLength = 0

    ' URLを解析
    Result = WinHttpCrackUrl(StrPtr(RequestData.Url), Len(RequestData.Url), 0, UrlComponents)

    ' パスが設定されていない場合はデフォルトのパスを追加
    If UrlPath = "" Then
        UrlPath = "/"
    End If

    ' ユーザー名とパスワードが設定されている場合は認証情報を追加
    If UserName <> "" And Password <> "" Then
        RequestData.Url = Scheme & "://" & HostName & ":" & Port & "/" & UrlPath & "?" & ExtraInfo
    Else
        RequestData.Url = Scheme & "://" & HostName & ":" & Port & "/" & UrlPath & "?" & ExtraInfo
    End If

    ' URLを設定
    Result = WinHttpOpenRequest(RequestData.hConnect, IIf(RequestData.Async, "GET", "GET"), StrPtr(RequestData.Url), vbNullString, vbNullString, 0, 0)

    SetWinHTTPRequestURL = Result
End Function

' WinHTTPリクエストのオプションを設定
Public Sub SetWinHTTPRequestOptions(ByRef RequestData As WinHTTPRequestData, ByVal hRequest As Long)
    Select Case RequestData.OptionType
        Case EnableRedirects
            WinHttpSetOption hRequest, WINHTTP_OPTION_DISABLE_FEATURE, WINHTTP_OPTION_DISABLE_REDIRECTS, 0
        Case DisableRedirects
            WinHttpSetOption hRequest, WINHTTP_OPTION_ENABLE_FEATURE, WINHTTP_OPTION_DISABLE_REDIRECTS, 0
        Case EnableSsl
            WinHttpSetOption hRequest, WINHTTP_OPTION_DISABLE_FEATURE, WINHTTP_OPTION_SECURE_PROTOCOLS, 0
        Case DisableSsl
            WinHttpSetOption hRequest, WINHTTP_OPTION_ENABLE_FEATURE, WINHTTP_OPTION_SECURE_PROTOCOLS, 0
        Case EnableSecureProtocols
            Dim SecureProtocols As Long
            SecureProtocols = 0
            If RequestData.OptionFlag And 1 Then
                SecureProtocols = SecureProtocols Or &H2  ' WINHTTP_FLAG_SECURE_PROTOCOL_TLS1
            End If
            If RequestData.OptionFlag And 2 Then
                SecureProtocols = SecureProtocols Or &H8  ' WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1
            End If
            If RequestData.OptionFlag And 4 Then
                SecureProtocols = SecureProtocols Or &H20  ' WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
            End If
            WinHttpSetOption hRequest, WINHTTP_OPTION_SECURE_PROTOCOLS, SecureProtocols, Len(SecureProtocols)
        Case EnableTrailingHeaders
            WinHttpSetOption hRequest, WINHTTP_OPTION_ENABLE_FEATURE, WINHTTP_OPTION_ENABLE_TRAILING_HEADERS, 0
        Case DisableTrailingHeaders
            WinHttpSetOption hRequest, WINHTTP_OPTION_DISABLE_FEATURE, WINHTTP_OPTION_ENABLE_TRAILING_HEADERS, 0
        Case EnableCookieHeaders
            WinHttpSetOption hRequest, WINHTTP_OPTION_ENABLE_FEATURE, WINHTTP_OPTION_ENABLE_HTTP_COOKIES, 0
        Case DisableCookieHeaders
            WinHttpSetOption hRequest, WINHTTP_OPTION_DISABLE_FEATURE, WINHTTP_OPTION_ENABLE_HTTP_COOKIES, 0
    End Select
End Sub

' WinHTTP同期リクエストの送信
Public Function SendWinHTTPRequestSync(ByRef RequestData As WinHTTPRequestData) As Boolean
    Dim hRequest As Long
    Dim Result As Boolean
    ' WinHTTPのリクエストを初期化
    hRequest = WinHttpOpenRequest(RequestData.hConnect, IIf(RequestData.Async, "GET", "GET"), StrPtr(RequestData.Url), vbNullString, vbNullString, 0, 0)
    ' ヘッダーの設定
    SetWinHTTPRequestHeaders RequestData, hRequest
    ' Content-Typeの設定
    SetWinHTTPRequestContentType RequestData, hRequest
    ' Content-Dispositionの設定
    SetWinHTTPRequestContentDisposition RequestData, hRequest
    ' URLの設定
    Result = SetWinHTTPRequestURL(RequestData)
    If Not Result Then
        GoTo CleanUp
    End If
    ' オプションの設定
    SetWinHTTPRequestOptions RequestData, hRequest
    ' WinHTTPリクエストデータの設定
    SetWinHTTPRequestData RequestData, hRequest
    ' WinHTTPリクエストの送信
    Result = WinHttpSendRequest(hRequest, vbNullString, 0, vbNullString, 0, 0, 0)
    ' WinHTTPリクエストが成功したらレスポンスを取得
    If Result Then
        Result = WinHttpReceiveResponse(hRequest, 0)
        If Result Then
            ' レスポンスヘッダーの取得
            Result = GetWinHTTPResponseHeaders(hRequest, RequestData)
            If Result Then
                ' レスポンスデータの取得
                Result = GetWinHTTPResponseData(hRequest, RequestData)
            End If
        End If
    End If

CleanUp:
    ' WinHTTPのリクエストをクローズ
    CloseWinHTTPRequestSync RequestData

    SendWinHTTPRequestSync = Result
End Function

' WinHTTP非同期リクエストの送信
Public Function SendWinHTTPRequestAsync(ByRef RequestData As WinHTTPRequestData) As Boolean
    Dim hRequest As Long
    Dim Result As Boolean
    ' WinHTTPのリクエストを初期化
    hRequest = WinHttpOpenRequest(RequestData.hConnect, IIf(RequestData.Async, "GET", "GET"), StrPtr(RequestData.Url), vbNullString, vbNullString, 0, 0)
    ' ヘッダーの設定
    SetWinHTTPRequestHeaders RequestData, hRequest
    ' Content-Typeの設定
    SetWinHTTPRequestContentType RequestData, hRequest
    ' Content-Dispositionの設定
    SetWinHTTPRequestContentDisposition RequestData, hRequest
    ' URLの設定
    Result = SetWinHTTPRequestURL(RequestData)
    If Not Result Then
        GoTo CleanUp
    End If
    ' オプションの設定
    SetWinHTTPRequestOptions RequestData, hRequest
    ' WinHTTPリクエストデータの設定
    SetWinHTTPRequestData RequestData, hRequest

    ' WinHTTP非同期イベント用のリクエストを作成
    RequestData.hWinHTTPOptionEvent = CreateWinHTTPOptionEvent(RequestData)
    ' WinHTTP非同期イベントの関連付け
    Result = WinHttpSetStatusCallback(hRequest, AddressOf WinHTTPOptionCallback, WINHTTP_CALLBACK_STATUS_HANDLE_REDIRECT Or WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE Or WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE Or WINHTTP_CALLBACK_STATUS_READ_COMPLETE Or WINHTTP_CALLBACK_STATUS_SEND_COMPLETE Or WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE Or WINHTTP_CALLBACK_STATUS_REQUEST_ERROR Or WINHTTP_CALLBACK_STATUS_SECURE_FAILURE Or WINHTTP_CALLBACK_STATUS_CONNECTING To WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, 0)
    If Not Result Then
        GoTo CleanUp
    End If
    ' WinHTTP非同期リクエストの送信
    Result = WinHttpSendRequest(hRequest, vbNullString, 0, vbNullString, 0, 0, 0)

CleanUp:
    ' WinHTTPのリクエストをクローズ
    If Not Result Then
        CloseWinHTTPRequest RequestData
    End If

    SendWinHTTPRequestAsync = Result
End Function

' WinHTTPレスポンスヘッダーの取得
Public Function GetWinHTTPResponseHeaders(ByVal hRequest As Long, ByRef RequestData As WinHTTPRequestData) As Boolean
    Dim dwSize As Long
    Dim Result As Boolean
    Dim lHeaderIndex As Long
    Dim lpBuffer As String
    Dim lpdwBufferLength As Long

    ' ヘッダーのサイズを取得
    Result = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, ByVal 0&, dwSize, WINHTTP_NO_HEADER_INDEX)
    If Result Then
        ' ヘッダーのサイズ分のメモリを確保
        lpBuffer = Space(dwSize + 1)
        ' ヘッダーの取得
        Result = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, ByVal StrPtr(lpBuffer), dwSize, WINHTTP_NO_HEADER_INDEX)
        If Result Then
            ' ヘッダーをResponseHeadersに格納
            RequestData.ResponseHeaders = lpBuffer
        End If
    End If

    GetWinHTTPResponseHeaders = Result
End Function

' WinHTTPレスポンスデータの取得
Public Function GetWinHTTPResponseData(ByVal hRequest As Long, ByRef RequestData As WinHTTPRequestData) As Boolean
    Dim dwSize As Long
    Dim dwDownloaded As Long
    Dim lpBuffer As String

    ' レスポンスデータのサイズを取得
    GetWinHTTPResponseData = WinHttpQueryDataAvailable(hRequest, dwSize)
    If GetWinHTTPResponseData Then
        ' レスポンスデータのサイズ分のメモリを確保
        lpBuffer = Space(dwSize)
        ' レスポンスデータの取得
        GetWinHTTPResponseData = WinHttpReadData(hRequest, ByVal StrPtr(lpBuffer), dwSize, dwDownloaded)
        If GetWinHTTPResponseData Then
            ' レスポンスデータをResponseDataに格納
            RequestData.ResponseData = lpBuffer
        End If
    End If
End Function

' WinHTTP非同期イベントの生成
Public Function CreateWinHTTPOptionEvent(ByRef RequestData As WinHTTPRequestData) As Long
    Dim hWinHTTPOptionEvent As Long
    ' イベントの生成
    hWinHTTPOptionEvent = CreateEventA(0, 0, 0, 0)
    ' グローバル変数に格納
    RequestData.hWinHTTPOptionEvent = hWinHTTPOptionEvent
    CreateWinHTTPOptionEvent = hWinHTTPOptionEvent
End Function

' WinHTTP非同期イベントハンドラ
Public Sub WinHTTPOptionCallback(ByVal hInternet As Long, ByVal dwContext As Long, ByVal dwInternetStatus As Long, ByRef lpvStatusInformation As Any, ByVal dwStatusInformationLength As Long)
    Dim RequestData As WinHTTPRequestData
    Dim EventData As WinHTTPOptionEventData

    ' ハンドラに対応するリクエストを取得
    Set RequestData = GetRequestDataByHandle(hInternet)

    If Not RequestData Is Nothing Then
        ' イベントデータの初期化
        EventData = InitializeWinHTTPOptionEventData(dwInternetStatus, lpvStatusInformation, dwStatusInformationLength, RequestData)
        ' イベントハンドラの呼び出し
        If Not RequestData.AsyncCallback Is Nothing Then
            RequestData.AsyncCallback EventData
        End If

        ' 各イベントに応じた処理
        Select Case dwInternetStatus
            Case WINHTTP_CALLBACK_STATUS_HANDLE_REDIRECT, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, WINHTTP_CALLBACK_STATUS_CONNECTING, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
                ' 各ステータスに対する処理を追加
        End Select
    End If
End Sub

' イベントデータの初期化
Public Function InitializeWinHTTPOptionEventData(ByVal dwInternetStatus As Long, ByRef lpvStatusInformation As Any, ByVal dwStatusInformationLength As Long, ByRef RequestData As WinHTTPRequestData) As WinHTTPOptionEventData
    Dim EventData As WinHTTPOptionEventData
    ' イベントデータの初期化
    EventData.EventType = GetWinHTTPOptionEventType(dwInternetStatus)
    EventData.ErrorCode = GetWinHTTPOptionErrorCode(lpvStatusInformation)
    EventData.BytesTransferred = GetWinHTTPOptionBytesTransferred(lpvStatusInformation)
    EventData.BytesTotal = GetWinHTTPOptionBytesTotal(lpvStatusInformation)
    ' グローバル変数に格納
    RequestData.State = GetWinHTTPState(dwInternetStatus)
    InitializeWinHTTPOptionEventData = EventData
End Function

' イベントの種別を取得
Public Function GetWinHTTPOptionEventType(ByVal dwInternetStatus As Long) As WinHTTPOptionEventType
    Select Case dwInternetStatus
        Case WINHTTP_CALLBACK_STATUS_HANDLE_REDIRECT
            GetWinHTTPOptionEventType = ResolveName
        Case WINHTTP_CALLBACK_STATUS_CONNECTING
            GetWinHTTPOptionEventType = Connect
        Case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            GetWinHTTPOptionEventType = SendRequest
        Case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            GetWinHTTPOptionEventType = ReceiveResponse
        Case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            GetWinHTTPOptionEventType = WriteComplete
        Case WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            GetWinHTTPOptionEventType = ReadComplete
        Case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            GetWinHTTPOptionEventType = HandleClosing
        Case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSED
            GetWinHTTPOptionEventType = HandleClosed
        Case Else
            GetWinHTTPOptionEventType = None
    End Select
End Function

' エラーコードを取得
Public Function GetWinHTTPOptionErrorCode(ByRef lpvStatusInformation As Any) As Long
    On Error Resume Next
    GetWinHTTPOptionErrorCode = lpvStatusInformation.dwError
    On Error GoTo 0
End Function

' 転送されたバイト数を取得
Public Function GetWinHTTPOptionBytesTransferred(ByRef lpvStatusInformation As Any) As Long
    On Error Resume Next
    GetWinHTTPOptionBytesTransferred = lpvStatusInformation.dwBytesTransferred
    On Error Go To 0
End Function

' トータルバイト数を取得
Public Function GetWinHTTPOptionBytesTotal(ByRef lpvStatusInformation As Any) As Long
    On Error Resume Next
    GetWinHTTPOptionBytesTotal = lpvStatusInformation.dwTotalLength
    On Error GoTo 0
End Function

' WinHTTPの状態を取得
Public Function GetWinHTTPState(ByVal dwInternetStatus As Long) As WinHTTPState
    Select Case dwInternetStatus
        Case WINHTTP_CALLBACK_STATUS_HANDLE_REDIRECT
            GetWinHTTPState = WinHTTPStateRequestNotSent
        Case WINHTTP_CALLBACK_STATUS_CONNECTING
            GetWinHTTPState = WinHTTPStateRequestNotSent
        Case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            GetWinHTTPState = WinHTTPStateRequestSent
        Case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            GetWinHTTPState = WinHTTPStateReceivingResponse
        Case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            GetWinHTTPState = WinHTTPStateWritingToRequest
        Case WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            GetWinHTTPState = WinHTTPStateReadingFromResponse
        Case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            GetWinHTTPState = WinHTTPStateRequestSent
        Case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSED
            GetWinHTTPState = WinHTTPStateRequestNotSent
        Case Else
            GetWinHTTPState = WinHTTPStateRequestNotSent
    End Select
End Function

' ハンドルに対応するリクエストデータを取得
Public Function GetRequestDataByHandle(ByVal hInternet As Long) As WinHTTPRequestData
    Dim RequestData As WinHTTPRequestData
    On Error Resume Next
    Set RequestData = Requests(CStr(hInternet))
    On Error GoTo 0
    Set GetRequestDataByHandle = RequestData
End Function

' WinHTTPリクエストの非同期イベントの解除
Public Function SetWinHTTPOptionEvent(ByVal hRequest As Long, ByVal hEvent As Long) As Boolean
    SetWinHTTPOptionEvent = WinHttpSetStatusCallback(hRequest, 0, 0, 0)
    CloseHandle hEvent
End Function

' WinHTTP非同期イベントの待機
Public Function WaitForWinHTTPOptionEvent(ByVal hEvent As Long, ByVal dwMilliseconds As Long) As Long
    WaitForWinHTTPOptionEvent = WaitForSingleObject(hEvent, dwMilliseconds)
End Function

' グローバル変数のクリア
Public Sub ClearGlobalVariables()
    Set Requests = Nothing
End Sub

このコードは、VBAでWinHTTPを使用してHTTPリクエストを行うためのものです。非同期通信もサポートしており、イベントハンドリングも含まれています。特にHTTPの非同期通信を行う際には、WinHTTPの非同期イベントハンドリングが必要となります。コード全体は、HTTPリクエストの送信から非同期イベントの処理までを担当しています。

解説

コードは長いのですが、やっている事のポイントは少ないので以下で解説します。

モジュールの冒頭部分

Private Requests As Collection

この行では、Requestsという名前のCollectionをグローバル変数として宣言しています。このCollectionは、WinHTTPの各リクエストに関連するデータを格納するために使用されます。

WinHTTPリクエストデータを格納するクラス

Private Type WinHTTPRequestData
    hRequest As Long
    hEvent As Long
    State As WinHTTPState
End Type

WinHTTPRequestDataは、WinHTTPリクエストに関連するデータを格納するためのユーザー定義型(UDT)です。これにはリクエストのハンドル (hRequest)、イベントのハンドル (hEvent)、およびリクエストの状態 (State) が含まれています。

WinHTTP非同期イベントの定義

Private Enum WinHTTPState
    WinHTTPStateRequestNotSent
    WinHTTPStateRequestSent
    WinHTTPStateReceivingResponse
    WinHTTPStateWritingToRequest
    WinHTTPStateReadingFromResponse
End Enum

WinHTTPStateは、WinHTTPリクエストの状態を表す列挙型です。これにはリクエストが送信されていない状態、リクエストが送信された状態、レスポンスを受信中の状態などが含まれています。

ハンドルに対応するリクエストデータを取得

Public Function GetRequestDataByHandle(ByVal hInternet As Long) As WinHTTPRequestData
    Dim RequestData As WinHTTPRequestData
    On Error Resume Next
    Set RequestData = Requests(CStr(hInternet))
    On Error GoTo 0
    Set GetRequestDataByHandle = RequestData
End Function

この関数は、指定されたハンドルに対応するWinHTTPRequestDataを取得します。Requestsコレクションには各リクエストのハンドルに関連するデータが格納されており、この関数を使用してハンドルに対応するデータを取得できます。

WinHTTP非同期イベントの解除

Public Function SetWinHTTPOptionEvent(ByVal hRequest As Long, ByVal hEvent As Long) As Boolean
    SetWinHTTPOptionEvent = WinHttpSetStatusCallback(hRequest, 0, 0, 0)
    CloseHandle hEvent
End Function

この関数は、指定されたWinHTTPリクエストの非同期イベントを解除します。これは通常、リクエストが完了した後に呼び出され、非同期イベントを解除してハンドルをクリーンアップします。

WinHTTP非同期イベントの待機

Public Function WaitForWinHTTPOptionEvent(ByVal hEvent As Long, ByVal dwMilliseconds As Long) As Long
    WaitForWinHTTPOptionEvent = WaitForSingleObject(hEvent, dwMilliseconds)
End Function

この関数は、WinHTTP非同期イベントが発生するまでスレッドを待機します。hEventは非同期イベントのハンドルであり、dwMillisecondsは待機する最大時間(ミリ秒単位)です。通常はリクエストが完了するまで待機します。

グローバル変数のクリア

Public Sub ClearGlobalVariables()
    Set Requests = Nothing
End Sub

このサブルーチンは、すべてのグローバル変数をクリアし、リソースの解放を行います。通常はプログラムの終了時に呼び出されます。

以上が、このVBAコードの主要な部分の解説です。これをベースに、実際のアプリケーションに応じて必要な拡張やエラーハンドリングを追加してください。

まとめ


VBAを用いてWinHTTPを利用することで、非同期通信を容易に実装することができます。この記事では、WinHTTPの基本的な機能から始め、非同期通信の利点や活用法、具体的な実装例まで幅広く解説しました。

  1. WinHTTPの基本機能: WinHTTPはHTTPリクエストを送信し、サーバーからのレスポンスを受け取るための強力なツールです。その基本的な機能や必要な設定について理解しました。
  2. 非同期通信の利点: 非同期通信は処理の効率性を向上させ、ユーザーエクスペリエンスを向上させるために重要です。また、複数の通信を同時に行うことが可能です。
  3. 具体的な実装例: 提供されたVBAコードを通じて、WinHTTPを使用して非同期通信を行う方法を具体的に解説しました。さらに、活用例として通信の進捗状況やエラーハンドリングの追加実装方法も紹介しました。
  4. 拡張と応用: この基本的な実装をベースに、ファイルのアップロード、フォームデータの送信、認証の組み込みなど、実際のニーズに合わせた拡張が可能です。
  5. 非同期通信の活用: Excelや他のOfficeアプリケーションでの非同期通信の活用は、リアルタイムなデータ処理や外部サービスとの連携など、様々なシナリオで威力を発揮します。

この記事を通じて、VBAを用いたWinHTTPの非同期通信がどのように行われるかについて理解を深め、実践的なスキルの向上に繋げて下さい。