Selecting/actioning items in Kendo UI widgets using Excel VBA

后端 未结 3 1641
时光说笑
时光说笑 2021-01-03 17:32

Stuck - Need help !

I\'m trying to automate actioning items in an IE web page on our internal company site. I\'m able to fill out any kind of text object

相关标签:
3条回答
  • 2021-01-03 18:00

    This is how to select the first row of the kendoGrid:

    ie.Document.parentWindow.execScript "$('#drgdLease').data('kendoGrid').select('tr:eq(0)');"
    


    Below is a demo showing the equivalent code working on the official Kendo UI Grid Widget Demo page.

    Note the work-around for the possible race condition. While it may be that this particular race condition also applies in your case, there is another race condition that you need to be aware of.

    It's possible that, after having initiated the search for the lease number, and before the kendoGrid has finished updating, your code might attempt to select the first row. This would result in the first row of the default displayed data/previous search data being selected, and then the grid being updated, causing the selection to disappear.

    The work-around employed in the code below will not work in this case, as it will always (incorrectly) detect a selected row. A different workaround is needed. (I can think of a few - the most suitable probably depending on your exact use case.)

    '============================================================================================
    ' 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
    


    Sources:

    From the official Kendo UI API documentation for the select method1:

    Example - select the first and second table rows
    ...

    var grid = $("#grid").data("kendoGrid");
    grid.select("tr:eq(1), tr:eq(2)");
    

    Note that this is actually wrong. The first row is at index 0, not index 1. A string parameter for the select method is treated as a jQuery selector, and from the official jQuery API documentation for the :eq() selector2:

    eq selector

    Description: *Select the element at index n within the matched set.*

    jQuery(":eq(index)")

    index: Zero-based index of the element to match.


    Interestingly, the official Kendo UI API documentation for the tbody object gets it right though3:

    Example - get the first table row
    ...

    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

    0 讨论(0)
  • 2021-01-03 18:00

    Here is my attempt. I tried to explain as much as possible in the comments. Let me know how it's going, based on the HTML posted, it seems like this should work, but please let us know :)

    I'm assuming you already have an IE window open and need to get a pointer to that window. Update the "myWebSiteURL" in the getIEPointer function to be the URL of the site you are trying to access. Less is more in this case as I'm doing a wildcard match. E.g. looking for 'goo' would match a url of 'Good' and '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
    
    0 讨论(0)
  • 2021-01-03 18:01

    here is a shot in the dark .... lol

    this may be a similar page

    single step the code

    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
    
    0 讨论(0)
提交回复
热议问题