gpt4 book ai didi

vba - 后期绑定(bind) IHTML 元素

转载 作者:行者123 更新时间:2023-12-02 00:39:17 26 4
gpt4 key购买 nike

我正在尝试创建一个后期绑定(bind)的 VBA 项目来搜索网络。在某一时刻,我有以下代码(早期绑定(bind)):

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

当后期绑定(bind)时,这段代码会变成这样:(或者我是这么想的)

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

我猜测,问题在于 IHTMLRect 前面的 I,即 MSDN tells me表示网页上没有与其关联的实际对象的元素 - 因此将其分配给未指定的 Object 在代码中没有任何意义。 (这完全是猜测)

无论如何,早期绑定(bind)的代码工作正常,后期绑定(bind)的代码在 elemRect.bottom 处退出执行

这是为什么?我该如何解决它?

最佳答案

VBA 中的对象可以实现多个接口(interface),您可以调用的方法/属性取决于您用于访问对象的接口(interface)。一个简单的例子:

' 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

就 MSHTML 而言,我猜测像 getElementById 这样的方法会返回一个类似于 IHTMLElement 版本之一的接口(interface)。这意味着无法访问 IHTMLDivElement 等接口(interface)中定义的方法/属性。

IUnknown 有一个名为 QueryInterface 的方法用于获取对象实现的不同接口(interface)。但是,这不能在 VBA 中直接调用,因为 VBA 执行此操作的方法是使用带有适当接口(interface)的 Dim,然后使用 Set。仅当设置了必要的引用时才会编译,这反过来又破坏了后期绑定(bind)的目的。

有一个解决方法,使用 CallByName 。要返回到工作表示例,这有效:

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)

对于 MSHTML 问题,此方法有效(请注意,调用类型已更改为 VbMethod):

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

我对 COM 对象知之甚少,因此很可能还有其他我没有考虑到的问题

<小时/>

完整代码(改编自 your answer to another question )。由于 IE 需要一些时间才能关闭,快速连续地重复运行该函数会产生错误(有关类似问题,请参阅 this question)。如果您需要连续运行多个查询,请重新使用相同的 IE 对象:

Option Explicit

Public Function GOOGLE_COUNT(searchTerm As String, xRes As Long, yRes As Long, Optional timeout As Long = 10) As Long

Dim url As String
Dim objIE As Object
Dim currPage As Object
Dim stTimer As Double, tElapsed As Single
Dim valueResult As Object

'create URL to page with these image criteria
url = "https://www.google.com/search?q=" & searchTerm & _
"&tbm=isch&source=lnt&tbs=isz:ex,iszw:" & xRes & ",iszh:" & yRes

'initiating a new instance of Internet Explorer and asigning it to objIE
Set objIE = CreateObject("InternetExplorer.Application")

'Google images search
objIE.navigate url
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Set currPage = objIE.document
Dim myDiv As Object: Set myDiv = currPage.getElementById("fbar")
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
myDiv.ScrollIntoView
'Count the images
Set valueResult = currPage.getElementById("rg_s").getElementsByTagName("IMG")
GOOGLE_COUNT = valueResult.Length
objIE.Quit

End Function

Sub foo()

MsgBox GOOGLE_COUNT("St. Mary", 1366, 768)

End Sub

关于vba - 后期绑定(bind) IHTML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43662976/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com