この VBA データ取得関数がハングしているのはなぜですか?

この VBA データ取得関数がハングしているのはなぜですか?

URL からデータを取得するために、VBA でこの関数を作成しました。Access クエリで呼び出される別の関数からこの関数を呼び出しています。このコードは、コードのコメントに引用されている記事のコードから引用したものです。

'========================================================
Public Function sURLfetch(ByVal sURL As String) As String
'========================================================
' Return data found at a URL.

' From "www.MyExcelGenius.com/getting-data-from-a-website-in-json-format-using-vba/".
' Requires reference "Microsoft XML, v6.0".

Const bRunAsynch As Boolean = True
Const nProcessComplete As Integer = 4

Dim oRequest As MSXML2.XMLHTTP60
Set oRequest = New MSXML2.XMLHTTP60

Dim sResponse As String

With oRequest
    .Open "get", sURL, bRunAsynch
    .setRequestHeader "Content-Type", "application/json"
    .send

    Do While oRequest.ReadyState <> nProcessComplete
        DoEvents
      Loop
    
    sResponse = .responseText
  End With

sURLfetch = sResponse

'========================================================
End Function        ' sURLfetch()
'========================================================

この関数が呼び出されると、VBA がハングします。しかし、奇妙なことに、次の行にブレークポイントを設定すると、

Do While oRequest.ReadyState <> nProcessComplete

そして、そこから続行するように VBA に指示すると、正常に実行され、目的の結果が返されます。コードがそのブレークポイントで中断され、その後続行される限り、この処理が何度も繰り返され、適切な結果のシーケンスが返されます。ただし、そのブレークポイントを削除し、代わりにループの直後の行にブレークポイントを設定すると、次のようになります。

sResponse = .responseText

その後、ハングアップして何も得られません。

したがって、何らかの理由で、ループに入る前にブレークポイントによって一時停止するように指示されない限り、この関数はループでハングします。

ループの目的は、応答を記録する前にフェッチ プロセスが完了していることを確認することです。コードの動作を観察しましたが、ループは通常 0 回または 1 回繰り返されます。ループが繰り返される場合は、フェッチが不完全であり、終了する必要があったことを意味します。したがって、ループはフェッチ対象に必要です。また、何らかの理由で、ループの前にブレークポイントがある限り正常に動作するように見えますが、そうでない場合は不可解にハングします。

関数DoEvents、つまりループのコンテンツ全体は、ループの実行中にオペレーティングシステムが実行しているすべての処理をVBAに実行させるように指示するだけです。その関数呼び出しはオリジナルコードここに適応された機能のドキュメントがありますマイクロソフトそしてウェルズ

VBA をランダムな時間一時停止する関数の呼び出しを挿入して一時停止を自動化しようとしました。それでも関数がハングするのを防ぐことはできませんでした。

まとめ:

  • この関数は、ループの先頭でブレークポイントによって一時停止されている場合に機能します。
  • ブレークポイントなしで呼び出された場合、またはループの後にブレークポイントを指定して呼び出された場合は、ハングします。

この機能がハングする原因は何でしょうか? また、これを動作させるには何を変更すればよいでしょうか?

答え1

問題はコマンドasynchのパラメータをOpenに設定することだったようですTrue。その設定リクエストが完了する前に停止することを許可する、これがループを必要とする原因でしたDoEvents。そこで、そのパラメータを に変更しFalse、ループをコメントアウトしてみました。その後、関数は正常に動作するようになりました。

なぜか分からないオリジナルコードasynch=とループを使用しましたTrue。これが関数が動作しなかった原因のようです。

関連情報