IE11是否仍支持dispatchEvent/FireElement?VBA宏操作下拉框无法触发onChange事件技术求助
Hey there, let's dig into this problem you're facing with your internal page's RadComboBox (those rcb* classes give away it's a Telerik RadComboBox control!). The core issue here is that you're trying to manipulate the display-only input field directly, but this wrapped control stores its actual selected state elsewhere (in that hidden ProcessCenter_ID_ClientState field) and relies on its own internal JavaScript events—so simple value changes or generic keyup events won't cut it.
Here's what's going wrong with your current approach:
- The
ProcessCenter_ID_Inputis a readonly text box that only shows the selected value, not the source of truth for the control's state. - RadComboBox uses its own JS API to handle selection changes, so modifying the input's value doesn't update the control's internal state or trigger the necessary onChange logic.
Let's adjust your VBA code to simulate the actual user interaction that the control expects: clicking the dropdown arrow, selecting the desired option, and letting the control handle the rest.
Modified VBA Code
Dim document As HTMLDocument: Set document = ieTab.document Dim comboArrow As HTMLAnchorElement Dim comboItems As IHTMLElementCollection Dim targetItem As IHTMLElement Dim i As Integer For i = 1 To 8 ' Wait for the combo box input to load Dim processCnt As HTMLInputElement Set processCnt = ElementTimer(3, ieTab) ' Define the target location text we want to select Dim targetText As String Select Case i Case 1: targetText = "London" Case 2: targetText = "Prague" Case 3: targetText = "WUIB" Case 4: targetText = "Zurich" Case 5: targetText = "Norway" Case 6: targetText = "Sweden" Case 7: targetText = "Poland" Case 8: targetText = "Russia" End Select ' Step 1: Click the combo arrow to expand the dropdown Set comboArrow = document.getElementById("ProcessCenter_ID_Arrow") comboArrow.Click DoEvents ' Wait for dropdown to render ' Step 2: Find the target option in the dropdown list ' RadComboBox options have the class "rcbItem" Set comboItems = document.getElementsByClassName("rcbItem") For Each targetItem In comboItems If Trim(targetItem.innerText) = targetText Then ' Step 3: Click the target option to select it targetItem.Click DoEvents ' Wait for control to update state Exit For End If Next targetItem Next i ' Keep your existing ElementTimer function as-is Private Function ElementTimer(number As Integer, ieTab As InternetExplorer) Dim messageBoxHW As LongPtr On Error GoTo timer1 1: Select Case number Case 1 Set ElementTimer = ieTab.document.getElementsByClassName("rgNoRecords").Item(0) Case 2 ieTab.document.getElementById("gvReport_ctl00_ctl02_ctl00_ExportToExcelButton").Click Case 3 Set ElementTimer = ieTab.document.getElementById("ProcessCenter_ID_Input") If ElementTimer Is Nothing Then GoTo timer1 End Select On Error GoTo 0 Exit Function timer1: DoEvents messageBoxHW = FindWindow(vbNullString, "Message from webpage") If messageBoxHW > 0 Then SendMessage messageBoxHW, WM_CLOSE, 0, 0 Resume 1 End Function
Key Changes Explained
- Simulate User Click to Expand Dropdown: Instead of modifying the input directly, we click the
ProcessCenter_ID_Arrowanchor to open the dropdown—this triggers the control's internal logic to render the options. - Select the Target Option by Text: We look for the option element with the matching text (using the
rcbItemclass, which is standard for RadComboBox options) and click it. This tells the control to update its internal state, the display input, the hiddenClientStatefield, and fire the necessary change events. - Add
DoEventsCalls: These give IE time to render the dropdown and process the selection before moving on, which is crucial for wrapped controls that rely on asynchronous JS rendering.
Additional Troubleshooting Tips
- If the
rcbItemclass doesn't work, open IE11's Developer Tools (F12), expand the dropdown manually, and inspect the option elements to find their correct class name. - If the dropdown closes too quickly or options aren't found, you can add a small delay (e.g.,
Sleep 500) after clicking the arrow—just make sure to declareDeclare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)at the top of your module. - To verify the control's state is updated, check the value of
document.getElementById("ProcessCenter_ID_ClientState").valueafter selecting an option—it should change to reflect the new selection.
This approach works because we're interacting with the control the same way a human user would, which bypasses the need to manually trigger obscure JS events.
内容的提问来源于stack exchange,提问作者Radas




