通过Excel自动化IE:Dropdown的change事件触发失效求助
IE自动化下拉框触发事件失效问题排查解决思路
两年前我用VBA代码自动化IE操作下拉框完全正常,但近几个月代码失效了。目前设置下拉框选中项的代码能正常运行,下拉框显示第4个选项,但触发change事件的代码无法让IE识别选择完成,导致后续需要操作的下拉框无法显示。
现有代码
触发事件的工具代码
Private Sub TriggerEvent(htmlDocument As Object, htmlElementWithEvent As Object, eventType As String) Dim theEvent As Object htmlElementWithEvent.Focus Set theEvent = htmlDocument.createEvent("HTMLEvents") theEvent.initEvent eventType, True, False htmlElementWithEvent.dispatchEvent theEvent End Sub
网页抓取主代码
Private Sub SelectDropDown() ForceIEClose Set ie = CreateObject("InternetExplorer.Application") With ie .navigate "https://a810-dobnow.nyc.gov/publish/Index.html#!/" .Visible = True ' 设为false可提升运行速度 End With Do Until ie.readyState = 4: DoEvents: Loop Set htmlDoc = ie.document ' 旧版设备搜索按钮点击代码已注释,以下是新版按钮点击 htmlDoc.getElementsByClassName("card border-tiles shadow h-100 padY-2 device-off")(0).Click On Error Resume Next Set nodeDeviceTypeDropdown = htmlDoc.getElementById("DeviceOptions") ' 设备类型下拉框 Application.Wait (Now + TimeSerial(0, 0, 1)) On Error GoTo 0 If Not nodeDeviceTypeDropdown Is Nothing Then nodeDeviceTypeDropdown.selectedIndex = 4 ' 以下代码失效,无法触发后续逻辑 Call TriggerEvent(htmlDoc, nodeDeviceTypeDropdown, "change") End If End Sub
当前下拉框HTML代码
<select required="" class="form-control ng-pristine ng-empty ng-invalid ng-invalid-required ng-touched" id="DeviceOptions" ng-model="Criteria.DeviceOptions" ng-class="{'has-error': (IsDeviceSearchClick && !Criteria.DeviceOptions)}"> <option class="selectPlaceholder" name="device" value="" hidden="" selected="selected">Select Device Type</option> <option value="1">Boilers</option> <option value="2">Elevator</option> <option value="3">Crane Prototype</option> <option value="4">Crane Device</option> </select>
解决思路
1. 针对AngularJS框架的适配
页面使用了AngularJS(从ng-model、ng-class等指令可判断),单纯触发原生change事件无法触发框架内部的模型更新,建议直接修改绑定的模型值:
' 直接设置AngularJS模型值 htmlDoc.parentWindow.execScript("angular.element(document.getElementById('DeviceOptions')).scope().Criteria.DeviceOptions = '4';") ' 强制Angular应用更新视图 htmlDoc.parentWindow.execScript("angular.element(document.getElementById('DeviceOptions')).scope().$apply();")
2. 优化事件触发逻辑
如果坚持用事件触发方式,可尝试组合触发多个相关事件,模拟真实用户操作流程:
' 先聚焦、点击下拉框,再选择选项,最后触发事件 nodeDeviceTypeDropdown.Focus nodeDeviceTypeDropdown.Click Application.Wait Now + TimeSerial(0,0,1) nodeDeviceTypeDropdown.Options(4).Selected = True Call TriggerEvent(htmlDoc, nodeDeviceTypeDropdown, "focus") Call TriggerEvent(htmlDoc, nodeDeviceTypeDropdown, "change") Call TriggerEvent(htmlDoc, nodeDeviceTypeDropdown, "input")
3. 改用IE原生fireEvent方法
放弃createEvent方式,使用IE专属的fireEvent可能兼容性更好:
Private Sub TriggerEvent(htmlElementWithEvent As Object, eventType As String) htmlElementWithEvent.Focus htmlElementWithEvent.fireEvent "on" & eventType End Sub
调用时直接写:Call TriggerEvent(nodeDeviceTypeDropdown, "change")
4. 完善页面加载等待逻辑
原代码仅等待DOM加载完成,Angular应用可能还在初始化,可增加框架初始化等待:
' 等待Angular框架初始化完成 Do Until htmlDoc.parentWindow.execScript("return angular.element(document).injector() !== undefined;") DoEvents Application.Wait Now + TimeSerial(0,0,1) Loop
内容的提问来源于stack exchange,提问作者John Wilson
相关产品推荐
相关产品推荐

