0

I've made a macro that opens Internet Explorer, navigates to a particular web-page with a list of articles (each article has the same class, but different innertext), and clicks a particular article. So far everything works perfectly well (Part 1 in a code below). However, when I try to do exactly the same operation (but with different class and innertext) again (Part 2 in a code below) it either works or not absolutely (as I see it) randomly. Maybe someone can give me a clue what may make it run smoothly every time?

Moreover, it always works when I run it by steps (F8).

HTML codes for Part 1:

 <div class="article-title">Some text in russian</div>

Part 2:

 <a href="javascript:void(0);" class="js-popup-open" data-
 popup="callback">Some text in russian 2</a>

Here is what i made so far:

Private Declare PtrSafe Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds 
As Long)
Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hwnd As 
Long, ByVal nCmdShow As Long) As Long
Private Const SW_SHOWMAXIMIZED = 3

Sub sup()

Dim aEle As HTMLLinkElement
Dim aaEle As HTMLLinkElement

Dim objIE As Object

Dim hwnd As Long

Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True


  objIE.navigate "http://www.spark-interfax.ru/ru/services"

ShowWindow objIE.hwnd, SW_SHOWMAXIMIZED
  Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
'Sleep (3000) (tried both variants, doesnt help)

'Part 1

 For Each aEle In objIE.document.getElementsByClassName("article-title")

    Debug.Print aEle.innerText
     On Error Resume Next

    If aEle.innerText = "Some text in russian" Then Exit For
    Next aEle

   aEle.Click

   Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
'  Sleep (3000) (again, tried both)

  'Part 2
   For Each aaEle In objIE.document.getElementsByClassName("js-popup-open")

    Debug.Print aaEle.innerText
     On Error Resume Next

    If aaEle.innerText = "some text in russian 2" Then  Exit For
    Next aaEle
    aaEle.Click

    End Sub
Sviat Lavrinchuk
  • 324
  • 4
  • 10
  • Remove all `On Error Resume Next` statements and check if there are any errors in part 2. – omegastripes Feb 14 '18 at 14:35
  • @omegastripes, you were right! But I still don't understand it. If I delete only "On Error" in part 2 - nothing changes (macro skips part 2), but if I remove "On error" in part 1, I get a Run-time error '91' (Object variable or With block variable not set) on the line "aaEle.Click" (last line of the macro). I suppose it is because aaEle variable is assigned to nothing, but I see no relation between this and On Error in Part 1. – Sviat Lavrinchuk Feb 14 '18 at 14:46
  • @SviatLavrinchuk Once you set `On Error Resume Next`, you will have to set `On Error GoTo 0` so VBA will then raise errors. This directive suppresses all errors until told otherwise. – Brownish Monster Feb 14 '18 at 14:50
  • @Brownish Monster, anyway, it only showed the problem: aaEle variable in Part 2 does not get assigned to a HTMLelement that I want it to (as I understand, because "getElementsByClassName" simply does not find elements with such class, although at least one is present there for sure. – Sviat Lavrinchuk Feb 14 '18 at 14:55
  • And what I just cannot understand, that if I run Part 1 and Part 2 separately - everything is ok, I run them together but with f8 - again ok, together with f5 - in most cases it doesn't work (and rarely works! with the same code) – Sviat Lavrinchuk Feb 14 '18 at 15:06
  • @SviatLavrinchuk Most of the times when this happens, it is because it hasn't loaded. Try `DoEvents` after `Sleep 3000` (and uncomment the sleep). In my experience, I have found IE automation is easy to implement but isn't very reliable. On the other hand, `WinHttp.WinHttpRequest` might be more reliable but is harder to get to the correct destination. That said, whenever I have got `WinHttpRequest` to work, I found it worth the effort and much faster. Looking at your sample, if JavaScript is present then it might be out of the question, depending on what your aim is. – Brownish Monster Feb 14 '18 at 16:20
  • @SviatLavrinchuk If you go the IE automation route, you can check if an element exists, if not then `Sleep 3000 : DoEvents` until it does or for a maximum number of times. – Brownish Monster Feb 14 '18 at 16:23
  • Then don't use `Sleep`, never. Make a check which relied on certain element presense or quantity of elements on the webpage, like `If objIE.document.getElementsByClassName("article-title").length >= N Then Exit Do`, or `If Not IsNull(objIE.document.getElementById("nodeId")) Then Exit Do`, etc. – omegastripes Feb 14 '18 at 17:54
  • @ omegastripes, I tried adding right after DoEvents line at the end of Part 1 such line "Cells(1, 2).Value = objIE.LocationURL" (it copies the URL of the page to the Cell) and it copies the first page I navigate to, not the one that loads after I use aEle.Click in Part 1. Does that mean something? – Sviat Lavrinchuk Feb 15 '18 at 11:27
  • @SviatLavrinchuk That means that the page have not been loaded at the moment you tried to process it. After `.Navigate` you have to wait for IE is ready, then for document, and target node(s) is accessible, check `Do ... Loop`s in first code block for IE in [this answer](https://stackoverflow.com/a/43969543/2165759), and in my comment above. – omegastripes Feb 15 '18 at 21:45

0 Answers0