坚持 - 需要帮助!
我正在尝试在我们内部公司网站的IE网页中自动执行操作项目。我可以填写任何类型的文本对象,点击提交按钮等,但有几个项目位于网格/表格中(Kendo)网格)或下拉列表列表。我似乎无法弄清楚如何从这些网格/表格或下拉列表中进行选择。
我已经尝试了我能想到的一切,但无济于事。我使用了getElementById()
,getElementsByTagName()
,getElementsByName()
,甚至还有一些网络抓取技术。
不幸的是,由于网页位于内部网站上,因此没有其他人可以对其进行测试。
这是我的代码的主要部分
'After opening the web page, inserting a number, selecting the "search"
' (all from the VBA script), I have to use a "mousemove", "mousedown" and
' "mouseup" to select the item, whick is what the "myClick" subroutine does
myClick '<<< THIS IS WHAT I WANT TO GET RID OF >>>
'I left the following segment in to show that I'm able to do several other functions
myDocs = ie.Document.getElementById("DispatchComments").Value
If myInfo = True Then
ie.Document.getElementById("DispatchComments").Value = "__" & myCell5 & "__" & myDocs
Else: End If
'IF ESTIMATED TIME IS LESS THAN 0, ENTER 120 - Enter estimated time
If ie.Document.getElementById("TotalEstimatedTime").Value < 10 Then
ie.Document.getElementById("TotalEstimatedTime").Value = 120
Else: End If
End With
End Sub
`
输入租约号码并点击搜索按钮后,这是screen shot。我设法选择行的唯一方法是以编程方式在显示的三个白色背景区域之一中单击鼠标。我的代码使用mousemove
和坐标来选择行,向下滚动到坦克下拉列表并单击它打开,这样我就可以手动选择坦克编号。
这部分代码是我被困的地方
Set myChoice1 = ie.Document.getElementById("drgdLease").getElementsByTagName("tr")(1)
With myChoice1
.getElementsByTagName("td")(0).Focus '<<---Works all the way to here
.FireEvent ("onmouseover") '<<---No errors from this point on
.FireEvent ("onmousedown") 'but doesn't do anything
.FireEvent ("onmouseup")
.FireEvent ("onclick") '<<---some other things tried
.FireEvent ("ondblclick")
.FireEvent ("onselect")
td.innerText = value
td.innerHTML = value
End With
'<tr role="row" data-uid="db62d811-4337-477c-a0fd-0e9e036670bb">
' <td role="gridcell">998262</td> '<<---This is the info/row I need to select
' <td role="gridcell">HENDERSON (SMACKOVER) STORAGE</td>
' <td role="gridcell">ORYAN OIL & GAS</td>
检查我正在尝试选择的区域的元素显示此HTML
name="Result">
<div class="k-widget k-grid" id="drgdLease" style="-ms-touch-action: double-tap-zoom pinch-zoom;" data-role="grid">
<table class="k-selectable" role="grid" style="-ms-touch-action: double-tap-zoom pinch-zoom;" data-role="selectable">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead class="k-grid-header" role="rowgroup">
<tr role="row">
<th class="k-header k-with-icon" scope="col" data-title="Lease Number" data-index="0" data-field="LeaseCode" data-role="columnsorter">
<a tabindex="-1" class="k-header-column-menu" href="#">
<span class="k-icon k-i-arrowhead-s"></span>
</a>
<a class="k-link" href="/LeaseProfiles/GetLeasesSearch?Length=9&drgdLease-sort=LeaseCode-asc">Lease Number</a>
</th>
<th class="k-header k-with-icon" scope="col" data-title="Lease Name" data-index="1" data-field="LeaseName" data-role="columnsorter">
<a tabindex="-1" class="k-header-column-menu" href="#">
<span class="k-icon k-i-arrowhead-s"></span>
</a>
<a class="k-link" href="/LeaseProfiles/GetLeasesSearch?Length=9&drgdLease-sort=LeaseName-asc">Lease Name</a>
</th>
<th class="k-header k-with-icon" scope="col" data-title="Lease Operator" data-index="2" data-field="LeaseOperator.OperatorName" data-role="columnsorter">
<a tabindex="-1" class="k-header-column-menu" href="#">
<span class="k-icon k-i-arrowhead-s"></span>
</a>
<a class="k-link" href="/LeaseProfiles/GetLeasesSearch?Length=9&drgdLease-sort=LeaseOperator.OperatorName-asc">Lease Operator</a>
</th>
</tr>
</thead>
<!--
This is what the code looks like before selecting the item.
ie: before clicking anywhere on the row.
-->
<tbody role="rowgroup">
<tr role="row" data-uid="db62d811-4337-477c-a0fd-0e9e036670bb">
<td role="gridcell">998262</td>
<td role="gridcell">HENDERSON (SMACKOVER) STORAGE</td>
<td role="gridcell">ORYAN OIL & GAS</td>
</tr>
</tbody>
</table>
<!--
This is what the code changes to after clicking the row.
Note the class and arial are added on the `tr role` line, which may be binding the data.
-->
<tr role="row" data-uid="db62d811-4337-477c-a0fd-0e9e036670bb" class = "k-state- selected" arial = "true">
<td role="gridcell">998262</td>
<td role="gridcell">HENDERSON (SMACKOVER) STORAGE</td>
<td role="gridcell">ORYAN OIL & GAS</td>
答案 0 :(得分:2)
这是如何选择kendoGrid的第一行:
ie.Document.parentWindow.execScript "$('#drgdLease').data('kendoGrid').select('tr:eq(0)');"
以下是演示官方Kendo UI Grid Widget Demo页面上的等效代码的演示。
请注意可能的竞争条件的解决方法。虽然这种特殊竞争条件也适用于您的情况,但是另一个竞争条件是你需要注意的。
在开始搜索租约号码之后,之前 kendoGrid完成更新后,您的代码可能会尝试选择第一行。这将导致选择默认显示数据/先前搜索数据的第一行,然后然后更新网格,导致选择消失。
在这种情况下, 下面的代码中使用的解决方法将无效 ,因为它将始终(错误地)检测选定的行。需要一种不同的解决方法。 (我可以想到一些 - 最合适的可能取决于你的确切用例。)
'============================================================================================
' Module : <in any standard module>
' Version : 0.1
' Part : 1 of 1
' References : Microsoft Internet Controls [SHDocVw]
' Source : https://stackoverflow.com/a/46483783/1961728
'============================================================================================
' Required if late binding SHDocVw
Private Enum tagREADYSTATE
READYSTATE_UNINITIALIZED = 0
READYSTATE_LOADING
READYSTATE_LOADED
READYSTATE_INTERACTIVE
READYSTATE_COMPLETE
End Enum
Public Sub AutomateKendoUI()
' Create and use a new instance of IE
With New SHDocVw.InternetExplorer '##Late Binding: CreateObject("InternetExplorer.Application")
.Visible = True ' False is default
.Navigate "http://demos.telerik.com/kendo-ui/grid/index"
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
' Race Condition Work-Around
' Kendo UI may not have finished loading the Grid data before we invoke its select method.
' Therefore, we continue to invoke the method until a selected row is detected.
Do
.parentWindow.execScript "$('#grid').data('kendoGrid').select('tr:eq(0)');"
On Error Resume Next
Dim elm_tr As MSHTML.HTMLTableRow: Set elm_tr = .querySelector("#grid tr.k-state-selected")
On Error GoTo 0
Loop While elm_tr Is Nothing
End With
End With
End Sub
来自select
方法 official Kendo UI API documentation 的1:
示例 - 选择第一个和第二个表行
...var grid = $("#grid").data("kendoGrid"); grid.select("tr:eq(1), tr:eq(2)");
请注意,这实际上是 错误 。第一行是索引0,不是索引1. select方法的字符串参数被视为jQuery选择器,official jQuery API documentation表示:eq()
选择器< SUP> 2 :
eq选择器
说明:*在匹配的集合中选择索引
n
的元素。*要匹配的元素的
jQuery(":eq(index)")
索引: 零 的索引。
有趣的是,tbody
对象的official Kendo UI API documentation通过 3 得到了正确的结果:
示例 - 获取第一个表格行
...var grid = $("#grid").data("kendoGrid"); var row = grid.tbody.find("tr:eq(0)");
<子>
1 http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#methods-select
2 https://api.jquery.com/eq-selector/
3 http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#fields-tbody
子>
答案 1 :(得分:0)
这是一个在黑暗中的镜头....大声笑
这可能是一个类似的页面
单步代码
Option Explicit
Sub extractKendo()
' Dim IE As Object
' Set IE = CreateObject("InternetExplorer.Application")
Dim ie As InternetExplorer
Set ie = New InternetExplorer
ie.Visible = True
ie.navigate "http://demos.telerik.com/kendo-ui/grid/index"
While ie.readyState <> 4 Or ie.Busy
DoEvents
Wend
Dim doc As HTMLDocument
Set doc = ie.Document
Dim elm As IHTMLElementCollection
Set elm = doc.getElementsByClassName("k-link k-pager-nav")
elm(0).Click
elm(4).Click
elm(0).Click
elm(3).Click
elm(3).Click
elm(3).Click
elm(0).Click
Set elm = doc.getElementsByClassName("k-list-scroller")
Set elm = elm(1).getElementsByTagName("li")
elm(0).Click
elm(1).Click
elm(2).Click
elm(3).Click
ie.Quit
Set ie = Nothing
End Sub
答案 2 :(得分:0)
这是我的尝试。我试着在评论中尽可能多地解释。让我知道它是怎么回事,根据发布的HTML,似乎这应该有用,但请告诉我们:)
我假设您已经打开了IE窗口,需要获取指向该窗口的指针。将 getIEPointer 函数中的“ myWebSiteURL ”更新为您尝试访问的网站的网址。在这种情况下,因为我正在进行通配符匹配,所以更少。例如。寻找'goo'会匹配'Good'和'Google'的网址。
Option Explicit
Public Sub getElements()
Dim ie As Object
'I'm assuming you already have it open in IE, if not, then load the page
Set ie = getIEPointer("myWebSiteURL")
'Exit if the window couldn't be located
If ie Is Nothing Then
Debug.Print "No Window Found!"
Exit Sub
End If
Dim element As Object
'get the Div element which contains all the elements we are interested in
'If this doesn't work, make sure your pages doesn't contain FRAMES
'Here's a page about Frames
'https://stackoverflow.com/questions/16699267/vba-ie-automation-read-iframe
Set element = ie.Document.getElementById("drgdLease")
'Select the first instance of the tbody element in the drgdLease div
Set element = element.getElementsByTagName("tbody")(0)
'Select the first instance of the td, inside the TBody
Set element = element.getElementsByTagName("td")(0)
'Interact with the element
element.Click
element.Value = "12345"
End Sub
'This function will return an IE object, I'm assuming the page is already open
Private Function getIEPointer(ByRef UrlPart As String) As Object
Dim window As Object
For Each window In CreateObject("Shell.Application").Windows()
If window.LocationURL Like "*" & UrlPart & "*" Then
Set getIEPointer = window
Exit Function
End If
Next
Set getIEPointer = Nothing
End Function