Прошу помочь в вопросе взаимодействия браузера с макросом. Исполнение макроса происходит при уже открытом браузере, то есть, макрос запускается из книги Эксель, а браузер уже открыт заранее на нужном сайте. Открыто строго только одно окно браузера. В ходе исполнения макроса происходит заполнение веб форм, нажатие кнопок типа submit и др. На последнем этапе макроса нажимается кнопка на сайте, которая приводит к открытию нового отдельного окна браузера (не вкладки, а именно окна). Новое окно открывается с задержкой в 2-5 секунд Вопрос: можно ли каким-либо образом перехватить момент, когда в конце исполнения макроса открывается еще одно окно браузера, чтобы уже на него отправить команду?
На ум пришел вариант с паузой в исполнении макроса и уже после паузы проверить на количество открытых окон браузера, но проблема в том, что новое окно браузера может открыться с различной задержкой - может 2 секунды, а может и 5, возможно, даже и больше. В связи с этим, пауза периодически может давать сбой или нужно будет ставить слишком большой интервал паузы.
Перед исполнением макроса, открытый браузер перехватываю при помощи следующего кода:
Код
Const sApplicationName As String = "Internet Explorer"
Dim oShellWindows As New SHDocVw.ShellWindows
Dim oIE As SHDocVw.WebBrowser
Dim bFlag As Boolean
If oShellWindows.Count = 0 Then
MsgBox "IE не открыт!", vbCritical
Exit Sub
End If
For Each oIE In oShellWindows
If oIE.Application = sApplicationName Then
bFlag = True
oIE.document.Focus
Exit For
End If
Next oIE
If bFlag = False Then
MsgBox "IE не открыт!", vbCritical
Exit Sub
End If
Извиняюсь за поднятие поста в топ своим же ответом.
Почитав форумы, на ум пришла мысль, что для данной задачи можно воспользоваться конструкцией, которая будет проверять условие и если оно не достигнуто, то будет ждать установленное время, а потом опять проверять совершилось ли условие и, если оно совершилось, то запускать код макроса дальше.
Подскажите, пожалуйста, можно ли такую конструкцию составить? Можно ли это сделать при помощи команды Sleep?
Sub TT()
Set Web1 = CreateObject("InternetExplorer.Application")
Web1.Visible = True
Web1.Navigate "адрес сайта"
Do While Web1.ReadyState <> 4: DoEvents: Loop
MsgBox "IE открыт"
'...
End Sub
это про создание совсем нового окна но строка 5 отвечает за ожидание, пока страница в новом окне не прогрузится полностью... *** для sleep() надо 1-й строкой прописывать
Код
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
P.S. ваш код, полагаю, отсюда ... в вопрос не вникаю (не считаю оптимальным) - думаю, может есть более рациональные варианты, чем ваш? - грузить html (функция GetHttpResponse), чем считать окна открытые... изучайте трафик вашего сайта через Fiddler...
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Const LocURL As String = "https://www.google.ru/"
Sub Test()
Dim oShellWindows As New SHDocVw.ShellWindows
Dim oIE As SHDocVw.WebBrowser
If oShellWindows.Count = 0 Then
MsgBox "IE не открыт!", vbCritical
Exit Sub
End If
Do While True
For Each oIE In oShellWindows
If oIE.LocationURL = LocURL Then
MsgBox "Открыт ГУГЛ!", vbInformation
oIE.document.Focus
Exit Do
End If
Next oIE
DoEvents
Sleep (100)
Loop
End Sub
Открываем IE, запускаем макрос, вводим ссылку как в константе и ждем результата. Вместо LocationURL можно использовать LocationName. Все зависит от web-страницы.
Расположил Ваш код в конце макроса, т.к. новое окно открывается при окончании макроса и автоматическом нажатии на кнопку на сайте. То есть, мне необходимо прямо в конце макроса перехватить открытие окна. Но макрос ругается на строку Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long), говоря, что не может в том месте быть Sub. А без этой строчки, насколько я понял, не работает Sleep(100). Скажите, пожалуйста, как можно интегрировать Ваш код в существующий макрос, чтобы он срабатывал прямо последним в строках кода макроса?
Но теперь возникла новая проблема :-) Макрос срабатывает при открытии нового окна в IE с соответствующим URL, но, видимо, макрос видит новое окно уже на уровне процессов, а визуально новое окно браузера открывается чуть попозже, секунд через 5-10, по-разному каждый раз. И с новым окном сразу открывается маленькое окошко печати в IE.
Подскажите, пожалуйста, можно ли отследить именно визуальное открытие нового окна IE? Пробовал доработать Ваш макрос так (вставив проверку Wifth и Height браузера так:
Код
eclare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Const LocURL As String = "https://www.google.ru/"
Sub Test()
Dim oShellWindows As New SHDocVw.ShellWindows
Dim oIE As SHDocVw.WebBrowser
If oShellWindows.Count = 0 Then
MsgBox "IE не открыт!", vbCritical
Exit Sub
End If
Do While True
For Each oIE In oShellWindows
If oIE.LocationURL = LocURL Then
If IE.Width > 100 and IE.Height > 100 then
IE.document.Focus
Application.Sendkys "{ENTER}"
Exit Do
End If
Next oIE
DoEvents
Sleep (100)
Loop
End Sub
Но этот метод не сработал)
И, если можно, вопрос: может ли VBA получить данные о том, что окно печати в IE открыто? Тогда все стало бы намного проще.
И Вас компилятор не послал искать отсутствующий end if ? Можно так отследить загрузку окна.Где elem-это любой элемент нового документа, который гарантировано будет при полной загрузке документа.
Код
If oIE.LocationURL = LocURL Then
set elem=IE.document.getElementById("MMM")
Do While elem is nothing
set elem=IE.document.getElementById("MMM")
doevents
'Сделать паузу 1/10 секунды
loop
IE.document.Focus
Application.Sendkys "{ENTER}"
Exit Do
End If
PS:Мне внутренний голос подсказывает, что большую часть телодвижений можно сделать запросами без браузера. Браузеру оставить роль печати файла.
Doober, все равно не хочет отправлять SendKeys :-)
Уже не знаю что с этим делать) Прошелся по разным форумам - итог тот же. Потом на ум пришла мысль получить в макросе окно печати IE и проверив его существование, отправить на него SendKeys. Но нигде так и не нашел как проверяется наличие открытого диалогового окна печати IE.
Проблема в том, что макрос на последнем этапе нажимает кнопку, после нажатия которой в браузере открывается новое окно и автоматически это окно открывается с уже открытым диалоговым окном печати IE и остается только нажать ENTER, чтобы печать началась. Но мне уже который день не удается отследить открытие окна и нажать эту кнопку ENTER при помощи SendKeys.
Новое окно в браузере открывается на весь экран. Если попробовать проверить новое окно по размерам и отправить SendKeys - это реально? То есть, если ширина и высота окна браузера больше, к примеру, 100, то фокус на окне и отправка SendKeys? Я попробовал сам провернуть такое, но не получилось( Может это технически невозможно в VBA?
Doober написал: PS:Мне внутренний голос подсказывает, что большую часть телодвижений можно сделать запросами без браузера. Браузеру оставить роль печати файла.
Doober, нет, сказать честно, не рассматривал, т.к. знаний в VBA пока не так много и до такого уровня не дошел) Но мне что-то подсказывает, что при помощи GET или POST запросов в моем случае не обойтись, т.к. в ходе заполнения форм приходится пару раз переходить на новую страницу, плюс ко всему, как я понимаю, HTML код сайта подгружается динамически, через :JS.
В принципе, сам макрос работает нормально, проблема осталась лишь в том, чтобы нажать кнопку Enter в нужное время, при появлении нового окна IE )