更新时间:2023-10-19 23:47:34
请尝试以下操作.实际上,它单击年份和月份的下拉菜单,然后通过itemindex
属性值选择适当的项目.
Try the following. It essentially clicks the dropdowns for year and month and selects the appropriate item by itemindex
attribute value.
在年份的情况下,取决于当前显示的内容,期望的年份可能不在下拉列表中.该代码使用<>按钮的固定点击次数来确定是否可以找到所需的年份.可以在代码顶部将该数字设置为一个常数,并在需要时进行更改.
In the case of year, depending on what is currently displayed, the desired year may not be in the drop down. The code uses a fixed number of clicks of the <> buttons to determine if the desired year can be found. This number could be set as a constant, at the top of the code, and altered there if required.
要选择日期,将循环收集天数,如果找到了所需的天数,则将其选中.
To select day, the collection of days is looped, and if the desired day value found then it is selected.
Javascript用于等待某些元素变为可单击状态,以及用于出现下拉菜单的定时循环.这会根据事件可采取行动的时间来计时,以产生预期的结果.
Javascript is used to wait for certain elements to become clickable, as well as a timed loop for a drop down to appear. This times events according to when they are actionable in order to yield desired results.
Option Explicit
Public Sub MakeChanges()
'VBE > Tools > References > Selenium Type Library
'Download: https://github.com/florentbr/SeleniumBasic/releases/tag/v2.0.9.0
Const url = "https://www.dukascopy.com/swiss/english/marketwatch/historical/"
Const MAX_WAIT_SEC As Long = 10
Const JS_WAIT_CLICKABLE = _
"var target = this, endtime = Date.now() + arguments[0];" & _
"(function check_clickable() {" & _
" var r = target.getBoundingClientRect(), x = r.left+r.width/2, y = r.top+r.height/2;" & _
" for (var e = document.elementFromPoint(x , y); e; e = e.parentElement)" & _
" if (e === target){ callback(target); return; }" & _
" if (Date.now() > endtime) { callback(target); return; }" & _
" setTimeout(check_clickable, 60);" & _
"})();" 'by @florentbr
Dim d As WebDriver, t As Date
Dim myYear As String, myMonth As String, myDay As String
Set d = New ChromeDriver
myYear = "2017"
myMonth = "January"
myDay = "1"
With d
.start "Chrome"
.get url
.SwitchToFrame .FindElementByCss("script + iframe") '<==switch to frame
'You should add tests for acceptable values e.g. January-December for MonthName, day as appropriate for month
Dim monthIndex As Long, yearIndex As Long, item As Object, dropDown As Object
monthIndex = Month(DateValue("01 " & myMonth & " 2019")) - 1 '<== get month number from name and -1 to get value to use in attribute selector
t = Timer
Do '<== timed loop for month dropdown to be present
On Error Resume Next
Set dropDown = .FindElementByCss(".d-wh-vg-xh span span")
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While dropDown Is Nothing
If dropDown Is Nothing Then Exit Sub
With dropDown '<== wait for drop down to be clickable
.ExecuteAsyncScript(JS_WAIT_CLICKABLE, 3000) _
.Click
End With
With .FindElementByCss(".d-Ch-fi-mi")
.ExecuteAsyncScript(JS_WAIT_CLICKABLE, 3000) _
.Click '<== display month dropdown
End With
.FindElementByCss(".d-Ch-fi-u [itemindex='" & monthIndex & "']").Click '<select month by index
Dim yearIndices As Object, i As Long, j As Long, currentYear As String, z As Long, dayFound As Boolean
currentYear = .FindElementByCss(".d-Ch-fi-ni").Text '<= find currently displayed year
Set yearIndices = CreateObject("Scripting.Dictionary")
For i = CLng(currentYear) - 5 To CLng(currentYear) + 5 '<== gather range of year options in dropdown into
'dictionary where key is year and value is the value required to select in attribute selector
yearIndices(CStr(i)) = CStr(j)
j = j + 1
Next
If yearIndices.Exists(myYear) Then '<check dictionary to see if year desired present
yearIndex = yearIndices(myYear)
.FindElementByCss(".d-Ch-fi-ni").Click '<== display year dropdown
.FindElementByCss("div:nth-child(11) [itemindex='" & yearIndex & "']").Click '<==select year
Else '<== year not present so loop clicking either year add or year subtract to see if desired year does become present
Dim adjustButton As Object
Set adjustButton = IIf(CLng(currentYear) > CLng(myYear),.FindElementByCss("d-Ch-fi-previousYear"), .FindElementByCss("d-Ch-fi-nextYear"))
Do
adjustButton.Click
If z > 15 Then Exit Sub
z = z + 1
Loop Until .FindElementByCss(".d-Ch-fi-ni").Text = myYear
End If
Dim daysList As Object
Set daysList = .FindElementsByCss("div:nth-child(11) td") '<==gather all the days
For Each item In daysList '<==loop days in month until required one found
If item.Text = myDay Then
item.Click
Exit For
End If
Next
Stop
.Quit
End With
End Sub