Is there a better way to accomplish this loop?

132 Views Asked by At

I'm pretty new with VBA, but I've been muddling through to make a program for my team. This piece of code works most of the time, but tends to hang on occasion. I can't figure out why it would hang sometimes, and work perfectly most of the time, so I'm now trying to figure out a better way to accomplish this loop. I know that this method of looping isn't the best way to do things, but not sure how to accomplish the task.

My webpage operates in a PEGA Web application, and the native IE ready state indicators are always 'ready' so I have to use the web application's ready state markers.

Can anyone help me out?

Public Sub WaitingForRS()
' FIND THE C360 WINDOW
        Marker = 0
        Set objShell = CreateObject("Shell.Application")
        IE_count = objShell.Windows.Count
        For x = 0 To (IE_count - 1)
            On Error Resume Next
            my_url = objShell.Windows(x).Document.Location
            my_title = objShell.Windows(x).Document.title

            If my_title Like "Coverage User" & "*" Then
                Set C360Window = objShell.Windows(x)
                Marker = 1
                Exit For
            Else
            End If
        Next

        If Marker = 0 Then
            MsgBox ("C360 window is not found. Please ensure C360 is open in Internet Explorer and try again")
        Else
        End If

'FIND THE READY STATE INDICATOR
    RSIndicatorDocMarker = 0
    RSIndicatorDataMarker = 0
    Set RSIndicatorPage = C360Window.Document
    Set RSIndicatorClass = RSIndicatorPage.getelementsbyclassname("document-statetracker")(0)

RSIndicatorCheck:
'CHECK THE READY STATE DOC STATUS
    If RSIndicatorClass.getattribute("data-state-doc-status") = "ready" Then
        RSIndicatorDocMarker = 1
        Else: RSIndicatorDocMarker = 0
    End If

'CHECK THE READY STATE
    If RSIndicatorClass.getattribute("data-state-busy-status") = "none" Then
        RSIndicatorDataMarker = 1
        Else: RSIndicatorDataMarker = 0
    End If

'Compare the RSIndicators
    If RSIndicatorDataMarker = 1 And RSIndicatorDocMarker = 1 Then

    Else: GoTo RSIndicatorCheck
    End If
End Sub
2

There are 2 best solutions below

0
Tim Williams On BEST ANSWER

Maybe try using OnTime instead of the tight loop you currently have:

Public Sub WaitingForRS()

    Dim win As Object
    Dim w As Object, el, ready As Boolean, idle As Boolean

    For Each w In CreateObject("Shell.Application").Windows
        If w.Name Like "*Internet*" Then
            If w.Title Like "Coverage user*" Then
                Set win = w
                Exit For
            End If
        End If
    Next

    If Not win Is Nothing Then

        Set el = win.document.getelementsbyclassname("document-statetracker")(0)
        ready = (el.getattribute("data-state-doc-status") = "ready")
        idle = (el.getattribute("data-state-busy-status") = "none")

        If ready And idle Then
            ProceedWithNextSteps win 'do whatever comes next: pass in the window
        Else
            'wait for a while then try again
            Application.OnTime Now + TimeSerial(0, 0, 1), "WaitingForRS"
        End If

    Else
        MsgBox "Window not found!"
    End If

End Sub

Might want to add a time limit so it doesn't keep looping forever if the page isn't "ready".

1
Peyter On

Check out my answer on this post Excel VBA Submitting data via IE on an online MS Forms not working

@ Idea 5 subheading. The WaitForLoadSETx() function has a manual time over-ride and double loop to help catch the state.

This was the best I could do in VBA with IE object. Ideally you want to learn Selenium, PhantomJS, or Puppeteer for actual browser manipulation. There are of course cool apps, folks have built on top of these libraries to help (puppeteer recorder chrome add in)

Or to keep things in Excel, use a simple XMLHTTPRequest object to cut the browser out of the equation, and deal solely with the request / response from the web page. This is a good alternative because it lets you focus on scraping the html content, in text form without the Javascript or waiting for page to load.