点击网站上iframe中没有ID的按钮?

时间:2017-09-15 04:28:05

标签: excel vba excel-vba button iframe

我尝试使用excel自动填充网络表单。我可以登录并填写iframe中的一些字段,但到目前为止我无法点击按钮,也无法填写iframe中的下拉列表。到目前为止,这是我的代码:

Sub AutoFill()
Dim ieApp As Object
Dim div As Variant

'create a new instance of ie
Set ieApp = CreateObject("InternetExplorer.Application")
ieApp.Visible = True

ieApp.navigate "webpage"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop

ieApp.document.all("login_email").Value = "username"
ieApp.document.all("login_password").Value = "password"
ieApp.document.all("login_button").Click

Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop

Dim button As HTMLInputButtonElement
Set button = _
ieApp.document.getElementById("internal_tab_text_client_products")
button.Focus
button.Click
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.readyState = READYSTATE_COMPLETE: DoEvents: Loop

'To fill in name on the web form:
Dim HTMLdoc As MSHTML.HTMLDocument
Dim htmlWindow As MSHTML.HTMLWindow2
Set HTMLdoc = ieApp.document
Set htmlWindow = HTMLdoc.frames(0)
htmlWindow.document.all("_text_5204102016102444865_FIELD").Value = _
ThisWorkbook.Sheets("sheet1").Range("a1")

Dim frame As HTMLFrameElement
Dim img
Set HTMLdoc = ieApp.document
Set frame = HTMLdoc.getElementsByName("main_content_window")(0)
Set HTMLdoc = frame.contentDocument

'Clicks a bubble on the webform
Set img = HTMLdoc.getElementById("_radioyn_227072016141926252_FIELD_NO")
img.Click

'to click the button (doesn't work):
Set img = HTMLdoc.getElementByTagName("button")
img.click
End Sub

当我开始点击我的代码中的按钮时,它有一个对象错误。我试图在网站上点击的按钮具有以下iframe代码:

<iframe
  id="main_content_window" 
  style="width:100%;height:99.5%;border:none;"
  onload="resizeEmbeddedPanel();"
  scrolling="yes"
  src="....php"
>

按钮略低于它,使用以下代码:

<button
  title="Start New"
  style="
          background-color: rgb(4,61,111);
          color:rgb(255,255,255);
          width:122px;
          height:33px;
          padding-left:0px;
          padding-right:0px;
          font-size:12px;
          font-weight:bold;
        "
  onclick="toggleNewBusinessMenu(); return false;"
>

修改

弄清楚了按钮!现在我只需要从iFrame中的下拉列表中选择帮助。以下是下拉列表的网站代码:

<select
  storage_var="1"
  object_id="F6F136889A5511E786D7F8BC12333350" 
  label_text="Choose+Program%3A" 
  linked_var="DM:Submission.none.policy.line_of_business" 
  context="F6F136889A5511E786D7F8BC12333350"
  data_type="Text" 
  id="F6F136889A5511E786D7F8BC12333350_droplist_127072016125151333_FIELD" 
  style="background-color:#FFFFFF;color:#000000;cursor:default;;width:100%;" 
  onselectstart="return true"
  field_data_type="Text" 
  onkeydown="top.onFieldKeyDown(event, window, 0);" 
  onkeyup="top.onFieldKeyUp(event, window, 0);" 
  onpaste="top.onFieldKeyUp(event, window, 0);"
  onblur="return 
  top.defaultBlurEvent(this, -1);"
  onchange="return window.ev_F6F136889A5511E786D7F8BC12333350_droplist_127072016125151333_action(event); "
  date_format="mm/dd/yy"
  value=""
  class=""
>
  <option value="">Please Select</option>
  <option value="HO_FLD">Home &amp; Flood</option>
  <option value="FLD">Flood Only</option>
</select>

1 个答案:

答案 0 :(得分:0)

您可以直接运行实际事件处理程序代码,而不是“点击”iframe中的按钮并间接运行事件处理程序代码。

以下内容应该有效:

htmlWindow.execScript("toggleNewBusinessMenu();", "JavaScript")

* 重要提示 *

iframe本质上是一个嵌入式 完全独立的 网页。因此,其元素不能直接从主DOM访问。您必须专门创建一个新的iframe DOM才能访问这些元素。如何执行此操作可以在下面的最后一个代码块中看到。

修改

要实际“点击”按钮,您可以通过枚举button这样的元素来找到该按钮:

Dim elmButton As MSHTML.IHTMLElement
For Each elmButton In HTMLdoc.getElementsByTagName("button")
  If elmButton.getAttribute("title") = "Start New" Then
    elmButton.Click
    Exit For
  End If
Next elmButton

请注意,.getElementsByTagName()方法会返回元素的集合。您的代码返回错误,因为您尝试使用不存在的.getElementByTagName()方法(缺少s)。


单击按钮的更好方法是使用querySelector()方法:

HTMLdoc.querySelector("button[title='Start New']").Click

修改

要从下拉列表中选择项目,请使用:

' Select "FLD" from droplist
HTMLdoc _
  .querySelector("select[id='F6F136889A5511E786D7F8BC12333350_droplist_127072016125151333_FIELD']") _
  .selectedIndex = 2

编辑:(v0.1.1)错误修复

我添加了代码的重写副本,演示了使用querySelector()方法访问DOM中对象的一致方式。我已经包含了一些记录使用DOM时存在某些缺陷的评论。

'============================================================================================
' Module     : <in any standard module>
' Version    : 0.1.1
' Part       : 1 of 1
' References : Microsoft HTML Object Library [MSHTML]
'            : Microsoft Internet Controls   [SHDocVw]
' Source     : https://stackoverflow.com/a/46232023/1961728
'============================================================================================
  ' Required if late binding MSHTML
  Private Enum tagREADYSTATE
    READYSTATE_UNINITIALIZED = 0
    READYSTATE_LOADING
    READYSTATE_LOADED
    READYSTATE_INTERACTIVE
    READYSTATE_COMPLETE
  End Enum

Public Sub AutoFill()

  ' Create and use a new instance of IE
  With New SHDocVw.InternetExplorer '##Late Binding: CreateObject("InternetExplorer.Application")
    .Visible = True ' False is default

    .Navigate "<webpage>"
    Do Until .Busy = False And .ReadyState = SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE: DoEvents: Loop '##Late Binding: = tagREADYSTATE.READYSTATE_COMPLETE  ##No Enums: = 4

    ' Get and use the main DOM
    With .Document
      ' .all() is deprecated. Suggest you use .querySelector()
      ' In the rest of the code, change "id" to "name" or other attribute as required
      ' (Also strongly suggest you change "*" to the appropriate tag name)
      .querySelector("*[id='login_email']").Value = "username"
      .querySelector("*[id='login_password']").Value = "password"
      .querySelector("*[id='login_button']").Click
      Do Until .Busy = False And .ReadyState = SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE: DoEvents: Loop '##Late Binding: = tagREADYSTATE.READYSTATE_COMPLETE  ##No Enums: = 4

      .querySelector("*[id='internal_tab_text_client_products']").Click
      Do Until .Busy = False And .ReadyState = SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE: DoEvents: Loop '##Late Binding: = tagREADYSTATE.READYSTATE_COMPLETE  ##No Enums: = 4

      ' Get and use the iframe's DOM
      Dim domIFrame As MSHTML.HTMLDocument '##Late Binding: As Object
      Set domIFrame = .frames("main_content_window").Document ' Could use querySelector here too, but that requires 3 lines instead of 1
      ' domIFrame is required - using With .frames(0).Document -> Run-time error '438'@ .querySelector(…)
      With domIFrame
        ' Fill in name on the web form:
        .querySelector("*[id='_text_5204102016102444865_FIELD']").Value _
        = ThisWorkbook.Sheets("sheet1").Range("A1").Value2

        ' Click a radio button on the web form:
        .querySelector("*[id='_radioyn_227072016141926252_FIELD_NO']").Click

        ' Select "FLD" from droplist
        .querySelector("select[id='F6F136889A5511E786D7F8BC12333350_droplist_127072016125151333_FIELD']") _
          .selectedIndex = 2
        ' 0 = <option value="">Please Select</option>
        ' 1 = <option value="HO_FLD">Home &amp; Flood</option>
        ' 2 = <option value="FLD">Flood Only</option>

        ' Click the "Start New" button:
        .querySelector("button[title='Start New']").Click
      End With
    End With
  End With

End Sub