Отправка данных через IE в онлайн-форму MS не работает - PullRequest
0 голосов
/ 13 января 2020

Может кто-нибудь выяснить, что я делаю неправильно?

Когда я пытаюсь отправить данные в онлайн-форму MS, отправка завершается неудачно при нажатии кнопки отправки, поскольку данные в текстовом поле ввода исчезают.

Код, который я использую:

Sub Hello()

    Dim objIE As Object
    Dim URL As String
    Dim doc As HTMLDocument

    Dim oServ As Object
    Dim cProc As Variant
    Dim oProc As Object

    URL = "https://forms.office.com/Pages/ResponsePage.aspx?id=1tUOxOPgeU2DDHmR8zp8jnPOq1Zxq2ZMgF9BFdtxEI9UNTJUSlpaNVU3S0pYRDI0MzE3UkZZQzdZNi4u"

    Set objIE = CreateObject("InternetExplorer.Application")
    objIE.Visible = True
    objIE.navigate URL
    Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
    Set doc = objIE.document

    Set oServ = GetObject("winmgmts:")
    Set cProc = oServ.ExecQuery("Select * from Win32_Process")

    Dim input_text As String
    input_text = "Hello!"

    doc.getElementsByTagName("input")(0).Value = input_text
    doc.getElementsByTagName("input")(0).setAttribute("value") = input_text

    'Let us wait 5 secconds to see if the text was entered into the textbox
    Application.Wait (Now() + TimeValue("00:00:05"))

    doc.getElementsByTagName("button")(2).Click


    'Let us wait 10 secconds to see the results before terminating IE
    Application.Wait (Now() + TimeValue("00:00:10"))


    Set objIE = Nothing
    For Each oProc In cProc
      If oProc.Name = "iexplore.exe" Then
          'MsgBox "KILL"   ' used to display a message for testing pur
          oProc.Terminate  'kill exe
      End If
    Next

End Sub

Ответы [ 2 ]

0 голосов
/ 14 января 2020

Я пытался с Sendkeys (), и это решило проблему.

Вам необходимо заменить эти строки кода.

doc.getElementsByTagName("input")(0).Value = input_text
doc.getElementsByTagName("input")(0).setAttribute("value") = input_text

на строки кода ниже.

doc.getElementsByTagName("input")(0).Focus
SendKeys (input_text)

Полный модифицированный код:

Sub Hello()

    Dim objIE As Object
    Dim URL As String
    Dim doc As HTMLDocument

    Dim oServ As Object
    Dim cProc As Variant
    Dim oProc As Object

    URL = "https://forms.office.com/Pages/ResponsePage.aspx?id=1tUOxOPgeU2DDHmR8zp8jnPOq1Zxq2ZMgF9BFdtxEI9UNTJUSlpaNVU3S0pYRDI0MzE3UkZZQzdZNi4u"

    Set objIE = CreateObject("InternetExplorer.Application")
    objIE.Visible = True
    objIE.navigate URL
    Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
    Set doc = objIE.document

    Set oServ = GetObject("winmgmts:")
    Set cProc = oServ.ExecQuery("Select * from Win32_Process")

    Dim input_text As String
    input_text = "Hello!"

   ' doc.getElementsByTagName("input")(0).Value = input_text
   ' doc.getElementsByTagName("input")(0).setAttribute("value") = input_text

   doc.getElementsByTagName("input")(0).Focus
   SendKeys (input_text)

    'Let us wait 5 secconds to see if the text was entered into the textbox
    Application.Wait (Now() + TimeValue("00:00:05"))

    doc.getElementsByTagName("button")(2).Click


    'Let us wait 10 secconds to see the results before terminating IE
    Application.Wait (Now() + TimeValue("00:00:10"))


    Set objIE = Nothing
    For Each oProc In cProc
      If oProc.Name = "iexplore.exe" Then
          'MsgBox "KILL"   ' used to display a message for testing pur
          oProc.Terminate  'kill exe
      End If
    Next

End Sub

Выход:

enter image description here

0 голосов
/ 13 января 2020

Я бы не рекомендовал использовать IE для автоматизации отправки VBA-форм.

Вот мой опыт: вы тратите много времени, пытаясь решить, что произошло, потому что клик должен был сработать. ошибки. Или почему страница не загрузила все ошибки? или как мне дождаться загрузки страницы и щелкнуть, что ей нужно.

TBS: потратил слишком много времени, пытаясь заставить работать подобные вещи, и часто получая хороший результат. Я бы предложил использовать ваши DevTools (f12 в IE) на странице. Сначала нажмите на кнопку, как обычно, и посмотрите, что произойдет. Далее Нажмите кнопку, используя JavaScript run в разделе консоли. Это будет что-то очень похожее на ваш синтаксис кликов. Обратите внимание на то, какой элемент на самом деле выбирается с помощью инспектора в инструментах разработки и какой сценарий выполняется с событием.

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

 Call IE.document.parentWindow.execScript("document.all.myElement.focus();buttonMovimenti();", "JavaScript") 

Источник

Я добился гораздо большего успеха при использовании execScript для запуска OnClick (); события на странице / родительское окно. Просто имейте в виду, что iFrames может быть затруднительным, чтобы выяснить, какой документ вы выбираете, поэтому обязательно проверьте источник, чтобы увидеть, есть ли несколько html документов на тестовой странице.

В качестве альтернативы вы можете попытаться использовать методы HTTP post / get для отправки формы с объектом запроса VBA MSXML2.XMLHTTP и репликации отправки заголовков / форм, которые вы видите в DevTools на вкладке Сеть при нажатии кнопки. Это взяло бы время загрузки страницы из уравнения и сделало бы более упорядоченное представление.

РЕДАКТИРОВАТЬ ПРИМЕРЫ:

Вот подпункт, который я использовал для это цель выполнения скриптов.

Сначала протестируйте скрипт в консоли IE. В своем комментарии вы ссылаетесь на всю свернутую библиотеку JS. Что вы хотите сделать, это найти функцию из окна, которая выполняет отправку формы.

Public Sub RunScriptZ(IeObjectDoc As Object, sJavaScript As String)
'run any java script on a page

    Dim CurrentWindow As HTMLWindowProxy
    Set CurrentWindow = IeObjectDoc.parentWindow
    Call CurrentWindow.execScript(sJavaScript)


End Sub

Обычно форма отправляется с базовой функцией c, такой как submitForm (). Поэтому откройте DevTools с открытой страницей, затем go в Консоль и введите Document.submitForm (); в консоли и посмотрим что получится. Надеюсь, форма подает с этим. Тогда вы могли бы что-то вроде:

 Call RunScriptZ(objie.Document, "submitForm()")

Если это не сработает, иногда сайту нужно, чтобы вы щелкнули / наведите курсор, чтобы отправить форму. Вы можете попробовать эти варианты по отдельности или в сочетании, чтобы увидеть, воспроизводятся ли они на веб-странице.

Идея 1, Метод события пожара

Dim ieo As New SHDocVw.InternetExplorerMedium
Set ieoDoc = ieo.Document
ieoDoc.getElementById("buttonId").FireEvent ("Onclick")

Идея 2: Basi c Exe c Сценарий

Dim ieo As New SHDocVw.InternetExplorerMedium
Set ieoDoc = ieo.Document
Dim CurrentWindow As HTMLWindowProxy
Set CurrentWindow = ieoDoc.parentWindow
Call CurrentWindow.execScript("submitForm()") ''or whatever the JS function 
'name is that runs in console and triggers the event

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

Public Function TestLinkClick(linkelement As HTMLButtonElement, ForceClick 
As Boolean) As Boolean
 If ForceClick = True Then GoTo clickawaylabel

   If IsNull(linkelement.OnClick) = False Then
clickawaylabel:
    TestLinkClick = True
    Debug.Print "the link is clickable"
    Else 'the linkelement is not clickable

      TestLinkClick = False
       Debug.Print "the link is not clickable"

    End If

 End Function

Идея 4: заполнить коробку

Public Sub FillInBox(TextValue As String, BoxName As String, IECVdoc As Object)

'fill in a box on a html page
Dim tries As Integer
tries = 0

On Error GoTo errorhandler

If tries >= 3 Then GoTo HappyEnd

startAgain:
With IECVdoc
    .getElementById(BoxName).Value = TextValue
    .getElementById(BoxName).FireEvent ("onchange")
End With

GoTo HappyEnd
errorhandler:

''Call a wait timer I'm using a wait sub: WaitForLoadSETx(IECVdoc, 2, 3)
tries = tries + 1
GoTo startAgain

HappyEnd:
End Sub

Идея 5: Ожидание загрузки

Public Sub WaitForLoadSETx(ieo As Object, Maxtime As Integer, Maxtime2 As Integer)
' Wait for page to load before continuing

Dim sngTime As Single

'Const Maxtime As Integer = 5
'Const Maxtime2 As Integer = 10
    sngTime = VBA.Timer ' a snapshot of the timer at the time the subroutine starts



    ' Wait until the webpage is doing something ...                'READYSTATE_COMPLETE <<< replaced 9/16/13 to click quicker with interactive
    Do Until ieo.ReadyState <> READYSTATE_COMPLETE
        DoEvents
        If VBA.Timer > sngTime + Maxtime And VBA.Left(ieo.statusText, 4) = "Done" Then Exit Sub
        If VBA.Timer > sngTime + Maxtime2 And ieo.ReadyState = 4 Or ieo.ReadyState = "complete" Then Exit Sub 'added this to make a real max time 1-12-15 'aded OR complete 1/14/15
     '   If VBA.Left(IEo.StatusText, 4) = "" Then GoTo outloop
     Debug.Print "ONE LOOP Page Loading [" & VBA.Timer & "]/[" & sngTime + Maxtime & "]" & " [" & ieo.ReadyState & "]" & " [" & ieo.statusText & "]"  '<<<< added 1/02/14
    Loop
'outloop:
    ' ... and then wait for it to finish 'READYSTATE_INTERACTIVE  <<< replaced 9/18/13 to click quicker with interactive
    Do Until ieo.ReadyState = READYSTATE_COMPLETE
        DoEvents
        On Error GoTo 0
       ' If VBA.Timer > sngTime + Maxtime And VBA.Left(ieo.statusText, 4) = "Done" Then Exit Sub 'removed 1/14/15 because or error 438 not found on .statusText
        If VBA.Timer > sngTime + Maxtime2 And ieo.ReadyState = 4 Or ieo.ReadyState = "complete" Then Exit Sub 'added this to make a real max time 1-12-15 'aded OR complete 1/14/15
    Debug.Print "TWO LOOP Page Loading [" & VBA.Timer & "]/[" & sngTime + Maxtime & "]" & " [" & ieo.ReadyState & "]" '& " [" & 'ieo.statusText & "]" '<<<< added 1/02/14
    Loop

0:
End Sub

Удачи!

...