1

I found an unexpected (at least for me) behavior using a variable declared as Object in Excel-vba. I was trying to extract some data from an html page and so I was using a routine like this:

sub Test

Dim htmlPage As htmlDocument
'This is the interesting variable
Dim DataTable       As Object
Dim DataCollection  As Object

'Code to get the html page

Set DataTable = htmlPage.getElementById("a name")
Set DataCollection = DataTable.getElementsByClassName("another name")

' Code to use DataCollection

end Sub

If I try to run this code on the line Set DataCollection = DataTable.getElementsByClassName("another name") I get the error

Run-time error '438'

Object doesn't support this property or method

After the first Set command the DataTable variable has become of type Object/HTMLDivElement so in principle it should have the method getElementsByClassName.

What I do not understand is that if I declare the variable from the beginning as HTMLDivElement (without changing anything else in the cose) such as:

Dim DataTable       As HTMLDivElement

the above code runs correctly without errors. In that case the DataTable variable is of type HTMLDivElement/HTMLDivElement.

What is the difference in declaring a variable as generic Object vs specifying its type from the beginning? And why the first version of the code does not work?

Community
  • 1
  • 1
MeSS83
  • 349
  • 2
  • 7
  • 20
  • `ResultTable` is not define in what you posted... Do you meant to use `DataTable`? – R3uK Nov 12 '15 at 17:04
  • @R3uK yes sorry, I edited – MeSS83 Nov 12 '15 at 17:06
  • Ok; so if you want some info on this, it is called `Late Binding` and `Early Binding`! ;) http://stackoverflow.com/questions/10580/what-is-the-difference-between-early-and-late-binding – R3uK Nov 12 '15 at 17:10
  • Declaring `DataTable` as `Object` shouldn't prevent you from calling `getElementsByClassName` once you've set that to a div element on the page. Have you tried reproducing that? – Tim Williams Nov 12 '15 at 17:17
  • @TimWilliams yes, this is why I asked the question. I ran the code on the same element of the same page: if `DataTable` is `Object` i get the error, if it is `HTMLDivElement` it works fine – MeSS83 Nov 12 '15 at 17:21
  • @R3uK ok so the first code should be an example of `Late Binding` but why I cannot call the `getElementsByClassName` with `Late Binding` ? – MeSS83 Nov 12 '15 at 17:22
  • 1
    Same result here - have not seen this before. Searching around other related posts someone mentioned it being a known issue but didn't include any reference... – Tim Williams Nov 12 '15 at 17:33
  • 1
    See Kyle's answer here: http://stackoverflow.com/questions/18709911/pull-data-from-website-using-vba-excel-multiple-classname – Tim Williams Nov 12 '15 at 17:37
  • @TimWilliams thanks. At least now I know that it is not "standard" behavior but that I should expect this for "html" related cases :) – MeSS83 Nov 12 '15 at 17:47
  • I think that "getElementsByClassName" was introduced in the "IHTMLElement6" interface so I'd be interested to see whether: `TypeOf DataTable Is IHTMLElement6` returned True or False in each type of binding and also what was returned by `TypeOf DataTable Is IHTMLElement` in each case. The reference to "Microsoft HTML Object Library" will need to be kept as otherwise you will get an error about "User-defined type not defined" when making these tests – barrowc Nov 13 '15 at 01:56
  • @barrowc I did your test and the result is `True` for all 4 combinations: Early/Late binding and `IHTMLElement/IHTMLElement6` – MeSS83 Nov 13 '15 at 08:41
  • There's a possible workaround with "querySelectorAll" but I've no idea why late binding causes a problem with "getElementsByClassName". Workaround: `Set DataCollection = htmlPage.querySelectorAll(#aName .anotherName)` (find node with ID "aName" and return all descendants with class "anotherName"). The return type is slightly different but might still work for you. I've left this as a comment in case anyone can solve the original "getElementsByClassName" problem – barrowc Nov 14 '15 at 02:42

0 Answers0