我正在尝试创建一个后期绑定的VBA项目来搜索网络。有一点我有以下代码(早期绑定):
Dim currPage as HTMLDocument: Set currPage = objIE.document 'where objIE is set with Set objIE = CreateObject("InternetExplorer.application")
'(late bound as it is dim'd as Object)
Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar")
Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect
'Scroll until bottom of page is in view
Do Until elemRect.bottom > 0
currPage.parentWindow.scrollBy 0, 10000
Set elemRect = myDiv.getBoundingClientRect
Loop
此代码在后期绑定时变为此:(或者我认为)
Dim currPage as Object: Set currPage = objIE.document
Dim myDiv As Object: Set myDiv = currPage.getElementById("fbar")
Dim elemRect As Object: Set elemRect = myDiv.getBoundingClientRect
'Scroll until bottom of page is in view
Do Until elemRect.bottom > 0
currPage.parentWindow.scrollBy 0, 10000
Set elemRect = myDiv.getBoundingClientRect
Loop
问题,我猜,是I
前面的IHTMLRect
,MSDN tells me表示网页上没有与之关联的实际对象的元素它 - 因此将它分配给未指定的Object
只是在代码中没有任何意义。 (这是一个完整的猜测)
无论如何,早期绑定代码工作正常,后期绑定代码退出elemRect.bottom
执行
为什么会这样,我该如何解决?
答案 0 :(得分:2)
VBA中的对象可以实现多个接口,您可以调用的方法/属性取决于您用来访问该对象的接口。一个简单的例子:
reflect
对于MSHTML,我猜想像' This means access the object via the IUnknown interface
' IUnknown is the interface from which all other COM
' interfaces inherit
Dim x As IUnknown
Set x = ThisWorkbook.Worksheets(1)
' Commented out as this won't compile because the
' Name property isn't defined in IUnknown
' MsgBox x.Name
' This means access the object through the default
' interface associated with the Worksheet object type
Dim w As Worksheet
Set w = x
' Now we can get to the name (same object, different interface)
MsgBox w.Name
这样的方法正在返回一个类似getElementById
版本的接口。这意味着无法访问IHTMLElement
等接口中定义的方法/属性。
IUnknown有一个名为QueryInterface的方法,用于访问对象实现的不同接口。但是,无法在VBA中直接调用此方法,因为VBA执行此操作的方法是将IHTMLDivElement
与适当的接口一起使用,然后使用Dim
。只有在设置了必要的引用后才能编译,这反过来又会破坏后期绑定的目的。
使用CallByName有一种解决方法。要返回工作表示例,可以使用:
Set
对于MSHTML问题,这有效(请注意,调用类型更改为Dim x As IUnknown
Set x = ThisWorkbook.Worksheets(1)
' Commented out as this won't compile because the
' Name property isn't defined in IUnknown
' MsgBox x.Name
' Can get to the property via CallByName
MsgBox CallByName(x, "Name", VbGet)
):
VbMethod
我对COM对象知之甚少,所以可能还有其他问题我没有考虑
完整代码(改编自your answer to another question)。由于IE需要时间关闭,因此快速连续重复运行该功能会产生错误(有关类似问题,请参阅this question)。如果需要连续运行多个查询,请重复使用相同的IE对象:
Dim elemRect As Object: Set elemRect = CallByName(myDiv, "getBoundingClientRect",
VbMethod)
stTimer = Timer
'Scroll until bottom of page is in view
Do Until elemRect.bottom > 0 Or tElapsed > timeout 'timeout after n seconds
currPage.parentWindow.scrollBy 0, 10000
Set elemRect = CallByName(myDiv, "getBoundingClientRect", VbMethod)
tElapsed = Timer - stTimer
Loop