Почему эта функция извлечения данных VBA зависает?

Почему эта функция извлечения данных VBA зависает?

Я написал эту функцию на VBA для извлечения данных из URL. Я вызываю ее из другой функции, которая вызывается в запросе 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

затем он зависает и я ничего не получаю.

Итак, по какой-то причине эта функция зависает в цикле, если только ей не приказано сделать паузу с помощью точки останова перед входом в цикл.

Цель цикла — убедиться, что процесс извлечения завершен перед записью ответа. Я наблюдал за работой кода, и цикл обычно повторяется ноль или один раз. Когда он повторяется, это означает, что извлечение было неполным и его нужно было завершить. Так что цикл необходим для того, что я извлекаю. И по какой-то причине он, кажется, работает нормально, пока перед ним есть точка останова, но в противном случае загадочно зависает.

Функция DoEvents, все содержимое цикла, просто говорит VBA позволить операционной системе делать то, что она должна делать, пока выполняется цикл. Этот вызов функции находится висходный кодадаптированная здесь и там документация функцииМайкрософтиуэллср.

Я попытался автоматизировать паузу, вставив вызов функции, которая останавливает VBA на случайное время. Это не предотвратило зависание функции.

Краткое содержание:

  • Функция работает, если она остановлена ​​точкой останова в начале цикла.
  • Он зависает, если вызывается без точки останова или с точкой останова после этого цикла.

Что может быть причиной зависания этой функции и что можно изменить, чтобы она заработала?

решение1

Похоже, проблема была в установке asynchпараметра в Openкоманде на True. Эта настройкапозволяет остановить запрос до его завершения, что и сделало DoEventsцикл необходимым. Поэтому я попробовал изменить этот параметр на Falseи закомментировать цикл. После этого функция, похоже, работает нормально.

Я не знаю, почемуисходный кодиспользовал asynch= Trueи цикл. Похоже, именно это и заставило функцию не работать.

Связанный контент