Jendra found an interesting bug while automating Internet Explorer. The Document object has a dozen or so collections that allow you to access various components of the html document. For instance, you can use the Links collection to iterate through all the hyperlinks (anchor tags with an href attribute) or you can use the All collection to iterate HTMLElements of any type.
Jendra has an image tag with a name attribute of “links”. It seems when you have an element with a name attribute equal to the name of a collection. I’ve tested it with Links and All and I assume it screws up on any collection name.
I set up a couple of html docs; TestLinks.htm and TestLinks2.htm. In the TestLinks2, I changed the name attribute to “links1? and the code did not fail. Below is the code I used to test it.
I don’t see a decent workaround to this bug. Jendra decided to test the Typename of the objects in the loop and exit gracefully if it was different than expected. Of course that means the code won’t actually work, but at least it won’t throw an ugly run-time error.
Here’s the test code. When the Navigate line is changed to TestLinks2, no error. As it is, I get error 438 “Object doesn’t support this property or method”. In debug mode from the immediate window you can see why
?Typename(ieDoc.Links)
HTMLImg
Of course an HTMLImg object doesn’t have a Length property so the For i = 1 to… line fails.
Dim ieApp As InternetExplorer
Dim ieDoc As Object
Dim i As Long
Set ieApp = New InternetExplorer
ieApp.Navigate “/excel/TestLinks.html”
Do
DoEvents
Loop Until ieApp.ReadyState = READYSTATE_COMPLETE
Set ieDoc = ieApp.Document
Debug.Print “******Links collections”
For i = 1 To ieDoc.links.Length
Debug.Print i, Mid(ieDoc.links(i – 1).innertext, 1, 20), TypeName(ieDoc.links(i – 1))
Next i
Debug.Print
Debug.Print “******All collection”
For i = 1 To ieDoc.all.Length
Debug.Print i, Mid(ieDoc.all(i – 1).innertext, 1, 20), TypeName(ieDoc.all(i – 1))
Next i
End Sub
I’ve got two quite decent workaround for you. :)
One is to use early binding for the ieDoc object, which somehow seems to clarify the compiler’s mind and remove the confusion between “links” as an element name and as an element type. Add a reference to “Microsoft HTML object library”, declare ieDoc As HTMLDocument, and the loop works fine.
The other is to loop through all elements and check their typename. This works with both early and late binding.
For Each ieElem In ieDoc.body.all
If TypeName(ieElem) = “HTMLAnchorElement” Then
Debug.Print ieElem.innertext
End If
Next ieElem
When I copy and paste the above code into Excel’s VBA editor, it doesn’t register as a subroutine that I can actually run. My problem is that:
Dim ieApp As InternetExplorer
I don’t register “InternetExplorer” as a valid type, e.g. String, Long, Single, etc.
Can you help?
Thanks,
– Peter
Peter –
You must first set a reference (VB Editor’s Tools menu) to the IE object library.
– Jon
Very interesting site!