VBA Internet Explorer дождаться загрузки веб-страницы

Я знаю, что такие вопросы задавались раньше, но мой немного отличается и был довольно тревожным. Я имею дело с веб-страницей с формой с несколькими событиями, которые загружают больше страницы при заполнении определенных элементов в полях ввода. Когда эти события запускаются, страница загружается снова, но остается на том же URL с тем же nameprop. Я использую следующие типы методов как отдельно, так и вместе, чтобы обрабатывать ожидание загрузки страницы, но иногда VBA все еще удается продолжить выполнение и установить переменную HTMLDocument на страницу без соответствующей информации о ней, вызывающей отладку макроса. Вот те вещи, которые я пробовал до сих пор:

While IE.Busy
    DoEvents
Wend

Do Until IE.statusText = "Done"
    DoEvents
Loop

Do Until IE.readyState = 4
    DoEvents
Loop

Я даже попытался поместить эти события в цикл, как показано ниже, но это не совсем сработало, потому что свойство lastModified возвращает значение только до второго, и макрос вращается через поля достаточно быстро, чтобы он возвращал новая страница в ту же секунду:

Do Until IE.statusText = "Done" And IE.Busy = False And IE.ReadyState = 4 _
And IE.document.lastModified > LastModified ----or---- IE.document.nameprop = _
"some known and expected name prop here"
    While IE.Busy
        DoEvents
    Wend
    Do Until IE.statusText = "Done"
        DoEvents
    Loop
    Do Until IE.readyState = 4
        DoEvents
    Loop
Loop

даже это не может ждать достаточно долго, чтобы установить объект HTMLDocument, ведущий к отладке. Я созерцал установка следующего входного элемента и убедившись, что ничего в код дальше, но даже этого не получится 100%, потому что, как правило, входные элементы существуют в HTML, но скрыты до тех пор, пока соответствующее событие, которое не было бы проблемой, но не загружать их возможные выборы до после событие запускается. Это может быть странная страница.

в любом случае... не знаю, что еще добавить. Если есть что-то еще, что может быть полезно увидеть, просто спросите. Я думаю, что я ищу способ заставить VBA ждать, пока IE не узнает, что другая страница не находится на пути. Кажется, что он загружается несколько раз, прежде чем это будет полностью сделано.

Так... У кого-нибудь есть идеи?

EDIT: нашел несколько новых вещей, чтобы попробовать. До сих пор нет кости. Было предложено добавить эти попытки. Здесь является ли код, по какой-то причине экземпляр VBE и excel становятся не реагирующими при использовании этого подхода после запуска события, которое должно заполнить параметры элемента select... думая о попытке xml... вот код:

intCounter = 0
Do until intCounter > 2
    Do Until IE.Busy = False: DoEvents: Loop
    Do Until IE.ReadyState = 4: DoEvents: Loop
    Set HTMLDoc = IE.Document
    Do Until HTMLDoc.ReadyState = "complete"
    Set HTMLSelect = HTMLDoc.getElementById("ctl00$ctl00$MainContent$ChildMainContent$ddlEmployeeBranchCodes")
    intCounter = 0
    For each Opt in HTMLSelect
        intCounter = intCounter + 1
    Next Opt
Loop

основываясь на том, что я вижу на веб-странице, Я знаю, что где-то в этом цикле VBE и Excel становятся не реагирующими.

надеюсь, что это поможет... Я знаю, что это не помогло мне... Drats.

EDIT: просто я подумал добавить это. Когда дело доходит до автоматизации веб-страницы, по большей части, я больше не использовать IE. Я обнаружил, что это намного лучше, и обходит эту проблему асинхронного материала полностью, чтобы просто выполнять сообщения и получать себя. Не может быть лучшее решение, в зависимости от того, что вы пытаетесь сделать, но он работает довольно надежно, если вы посмотрите внимательно на движения и параметризовать все хорошо.

3 ответов


после исчерпывающего поиска я определил, что запрос AJAX, код javascript, который работает асинхронно в фоновом режиме, не является тем, от чего я могу получить сигнал каким-либо образом. Кажется, это вызывает какое-то событие, когда оно заканчивается загрузкой страницы, что является вариантом, который я хотел бы изучить в будущем. Однако для моих целей я просто использовал тот же код, который я уже использовал, чтобы заполнить форму на моей странице, и у меня есть цикл через каждое поле снова, чтобы проверить, если значения еще правильно, прежде чем нажать кнопку "Отправить". Это не идеальное решение, но это обходной путь, который, похоже, позаботился о моей проблеме в этом случае.

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


у меня была такая же проблема с моим веб-страницы.. То, что сделал...

опции кулак

While Ie.**document**.readystate="complete"
DoEvents
Wend

было несколько ящиков, в которых параметры были загружены после нажатия кнопки/даже пожара в другом окне...Я jsst разместил такой код..

Do Until IE.document.getelementbyid("Next box").Lenght>0
DoEvents
Loop
Application.wait Now+Timevalue("00:00:02)

старый вопрос я знаю, но я думаю, что это хороший ответ, который я не видел много...


Я похожие проблемы; ожидание загрузки всех изображений в поиске изображений google (что сложно, поскольку загрузка изображений запрашивается AJAX и пользователь прокручивает страницу). Как было предложено в комментариях; мое решение нужно было дождаться появления определенного элемента в окно просмотра (это площадь немного больше, чем экран монитора, и рассматривается как то, что вы действительно можете "видеть").

Это достигается с помощью тега getBoundingClientRect метод

Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar") 
'myDiv should some element in the page which will only be visible once everything else is loaded
Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect
Do Until elemRect.bottom > 0 'If the element is not in the viewport, then this returns 0
    DoEvents
    'Now run the code that triggers the Ajax requests
    'For me that was simply scrolling down by a big number
    Set elemRect = myDiv.getBoundingClientRect
Loop
myDiv.ScrollIntoView

я подробно объясняю в связанном ответе, как это работает, но по существу BoundingClientRect.bottom равно 0, пока элемент не находится в vieport.

элемент-это то, что загружается сразу (например, фрейм/шаблон для страницы). Но вы на самом деле не видите его, пока все содержимое не будет загружено, потому что это прямо внизу.

если этот элемент действительно последнее, что нужно загрузить (для моего поиска google это был Показать Больше Результатов), то пока вы получаете его в видовое окно, когда он загружен, вы должны быть в состоянии определить, когда это появляется на странице. .bottom затем возвращает ненулевое значение (что - то связанное с фактическим положением элемента на странице-мне было все равно, хотя для моих целей). Я заканчиваю с а .ScrollIntoView, но это не важно.