如何使用 VBA Excel 等待 Internet Explorer 9 框架加载?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10954496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 16:26:21  来源:igfitidea点击:

How does one wait for an Internet Explorer 9 frame to load using VBA Excel?

excelvbainternet-explorer-9

提问by user1444796

There are many online resources that illustrate using Microsoft Internet Explorer Controls within VBA Excel to perform basic IE automation tasks. These work when the webpage has a basic construct. However, when webpages contain multiple frames they can be difficult to work with.

有许多在线资源说明如何在 VBA Excel 中使用 Microsoft Internet Explorer 控件来执行基本的 IE 自动化任务。这些在网页具有基本结构时起作用。但是,当网页包含多个框架时,它们可能难以使用。

I need to determine if an individual frame within a webpage has completely loaded. For example, this VBA Excel code opens IE, loads a webpage, loops thru an Excel sheet placing data into the webpage fields, executes search, and then returns the IE results data to Excel (my apologies for omitting the site address).

我需要确定网页中的单个框架是否已完全加载。例如,这个 VBA Excel 代码打开 IE,加载一个网页,通过 Excel 工作表循环将数据放入网页字段中,执行搜索,然后将 IE 结果数据返回到 Excel(我很抱歉省略了站点地址)。

The target webpage contains two frames:

目标网页包含两个框架:

1) The searchbar.asp frame for search value input and executing search

1)searchbar.asp框架,用于搜索值输入和执行搜索

2) The searchresults.asp frame for displaying search results

2) searchresults.asp 显示搜索结果的框架

In this construct the search bar is static, while the search results change according to input criteria. Because the webpage is built in this manner, the IEApp.ReadyState and IEApp.Busy cannot be used to determine IEfr1 frame load completion, as these properties do not change after the initial search.asp load. Therefore, I use a large static wait time to avoid runtime errors as internet traffic fluctuates. This code does work, but is slow. Note the 10 second wait after the cmdGO statement. I would like to improve the performance by adding solid logic to determine the frame load progress.

在此构造中,搜索栏是静态的,而搜索结果会根据输入条件发生变化。由于网页是以这种方式构建的,因此 IEApp.ReadyState 和 IEApp.Busy 不能用于确定 IEfr1 框架加载完成,因为这些属性在初始 search.asp 加载后不会更改。因此,我使用较大的静态等待时间来避免因互联网流量波动而导致的运行时错误。此代码确实有效,但速度很慢。请注意 cmdGO 语句后的 10 秒等待。我想通过添加可靠的逻辑来确定帧加载进度来提高性能。

How do I determine if an autonomous frame has finished loading?

如何确定自主框架是否已完成加载?

' NOTE: you must add a VBA project reference to "Internet Explorer Controls"
' in order for this code to work
Dim IEapp As Object
Dim IEfr0 As Object
Dim IEfr1 As Object

' Set new IE instance
Set IEapp = New InternetExplorer

' With IE object
With IEapp
    ' Make visible on desktop
    .Visible = True
    ' Load target webpage
    .Navigate "http://www.MyTargetWebpage.com/search.asp"
    ' Loop until IE finishes loading
    While .ReadyState <> READYSTATE_COMPLETE
        DoEvents
    Wend
End With

' Set the searchbar.asp frame0
Set IEfr0 = IEapp.Document.frames(0).Document 

' For each row in my worksheet
For i = 1 To 9999                

    ' Input search values into IEfr0 (frame0)
    IEfr0.getElementById("SearchVal1").Value = Cells(i, 5)
    IEfr0.getElementById("SearchVal2").Value = Cells(i, 6)

    ' Execute search
    IEfr0.all("cmdGo").Click        

    ' Wait a fixed 10sec
    Application.Wait (Now() + TimeValue("00:00:10"))

    ' Set the searchresults.asp frame1
    Set IEfr1 = IEapp.Document.frames(1).Document

    ' Retrieve webpage results data
    Cells(i, 7) = Trim(IEfr1.all.Item(26).innerText)
    Cells(i, 8) = Trim(IEfr1.all.Item(35).innerText)

Next

回答by danielpiestrak

As @JimmyPena said. it's a lot easier to help if we can see the URL.

正如@JimmyPena 所说。如果我们能看到 URL,就更容易提供帮助。

If we can't, hopefully this overview can put you in the right direction:

如果我们不能,希望这个概述可以让你朝着正确的方向前进:

  1. Wait for page to load (IEApp.ReadyState and IEApp.Busy)
  2. Get the document object from the IE object. (done)
  3. Loop until the document object is not nothing.
  4. Get the frame object from the document object.
  5. Loop until the frame object is not nothing.
  1. 等待页面加载(IEApp.ReadyState 和 IEApp.Busy)
  2. 从 IE 对象中获取文档对象。(完毕)
  3. 循环直到文档对象不是空的。
  4. 从文档对象中获取框架对象。
  5. 循环直到框架对象不是空的。

Hope this helps!

希望这可以帮助!

回答by rds1975

I used loop option to check the field value until its populated like this

我使用循环选项来检查字段值,直到它像这样填充

Do While IE.Document.getElementById("USERID").Value <> "test3" IE.Document.getElementById("USERID").Value = "test3" Loop

执行 While IE.Document.getElementById("USERID").Value <> "test3" IE.Document.getElementById("USERID").Value = "test3" Loop

回答by Jon Dresser

this is a Rrrreeally old thread, but I figured I would post my findings, because I came here looking for an answer...

这是一个非常古老的线程,但我想我会发布我的发现,因为我来这里是为了寻找答案......

Looking in the locals window, I could see that the "readystate" variable was only "READYSTATE_COMPLETE" for the IE App itself. but for the iframe, it was lowercase "complete"
So I explored this by using a debug.print loop on the .readystate of the frame I was working with.

查看本地窗口,我可以看到 IE 应用程序本身的“readystate”变量仅为“READYSTATE_COMPLETE”。但是对于 iframe,它是小写的“完整”
所以我通过在我正在使用的框架的 .readystate 上使用 debug.print 循环来探索这个。

Dim IE As Object
Dim doc As MSHTML.HTMLDocument
Set doc = IE.Document
Dim iframeDoc As MSHTML.HTMLDocument
Set iframeDoc = doc.Frames("TheFrameIwasWaitingFor").Document

' then, after I had filled in the form and fired the submit event, 

Debug.Print iframeDoc.readyState
   Do Until iframeDoc.readyState = "complete"
     Debug.Print iframeDoc.readyState 
     DoEvents
   Loop

So this will show you line after line of "loading" in the immediate window, eventually showing "complete" and ending the loop. it can be abridged to remove the debug.prints of course.

因此,这将在立即窗口中显示一行一行的“加载”,最终显示“完成”并结束循环。当然,它可以被删减以删除 debug.prints。

another thing:

另一件事:

debug.print iframeDoc.readystate ' is the same as...
debug.print doc.frames("TheFrameIwasWaitingFor").Document.readystate
' however, you cant use...
IE.Document.frames("TheFrameIwasWaitingFor").Document.readystate ' for some reason...

forgive me if all of this is common knowledge. I really only picked up VBA scripting a couple days ago...

如果所有这些都是常识,请原谅我。我真的只是在几天前才开始学习 VBA 脚本...