VBA:查找新创建的HTML元素

时间:2016-02-12 00:11:28

标签: excel vba excel-vba

我正在尝试使用InternetExplorerMedium对象从网页中获取信息。获取信息的基本程序如下:

  1. 加载网页。
  2. 在2个可编辑的文本字段中输入开始日期和结束日期。
  3. 按“提交”按钮。 该页面然后运行一些javascript并将表加载到以前存在的容器中。这个容器里面是表格,还有一个菜单栏,下面有按钮,导出,刷新等。
  4. 等待5秒钟以执行javascript并显示表格。
  5. 单击此容器内的导出按钮以下载列出数据的Excel文件。
  6. 代码:

    Sub GetReport()
    Dim frm As Variant
    Dim TxtRng As Range
    
    'Load IE page
    Set IE = New InternetExplorerMedium
    IE.Visible = True
    IE.Navigate "http://example.com/page"
    
    'Wait until page is ready
    Do Until IE.ReadyState = 4
    
    Loop
    
    'Enter data into fields, press submit
    IE.Document.getElementsByName("userField1").Item(0).Value = Date
    IE.Document.getElementsByName("userField2").Item(0).Value = Date
    IE.Document.getElementsByName("submitButton").Item(0).Click
    
    'Wait for table to load, find export button
    Application.Wait (Now + TimeValue("00:00:05"))
    Set frm = IE.Document.getElementByID("exportButton")
    
    'Testing to see if frm was successfully grabbed
    Set TxtRng = ActiveWorkbook.Sheets("Sheet2").Range("A1")
    TxtRng.Value = frm.getAttribute("innerHTML")
    
    End Sub
    

    我已经实现了步骤1-4,但在尝试查找导出按钮的HTML元素时,收到错误:

      

    运行时错误'01':   对象变量或未设置块变量

    我做了一些故障排除,发现:

    • 搜索不存在的项目时会发生同样的错误。
    • 在执行“提交”按钮的javascript函数之前,所有未出现的元素都会出现同样的错误。
    • 搜索“提交”按钮的javascript函数执行之前存在的项目时,不会发生错误。
    • 使用getElementsbyName会产生相同的结果。
    • 我等待的时间超过了表格的加载时间。等待10,15,20秒不会改变结果。

    所以看起来getElementbyID和getElementsbyName找不到新创建的元素。没有标记任何元素,所以我不能使用getElementsbyTagName ...我是否需要以某种方式“刷新”InternetExplorerMedium对象,以便它可以检测对页面所做的更改?我看了一下对象引用,并没有看到这些行。当页面加载新元素时,ReadyState是否会发生变化?

    感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

The problem with your code is that you use Application.Wait. The problem with this is that InternetExplorer and Excel are both working on the same thread as you are controlling them both. So when you call Application.Wait which freezes Excel it will also freeze InternetExplorer and thus the insertion of new elements.

The answer is you need to let the thread run and for InternetExplorer to do its work. In VBA this is very difficult as you only have one thread. If you could move this to VB.net you could use threads.

My suggestion is that after you click the submit button you set up a timer which ticks every 1000 milliseconds. When this timer ticks check to see if the table you want is present. If not present let the timer go again, if present, end the timer and continue to find the button you want.

I have dealt with similar situations where the HTMLDocument is not refreshed but elements are added to it. In my case I was unable to find an event to wait for, I too could only set a timer and wait for it to tick and then check to see if the new elements are there.

If you do need help with finding this new element then you are going to need to either post a link or post some HTML. As you are using InternetExplorerMedium Im guessing it is an intranet site, so in that case try posting part of the html, even if it is just the new part inserted.

答案 1 :(得分:0)

import random def getscramble(): moves = ["R","F","U","L","B","D"] scramble = [] finascramble = [] for x in range(25): scramble.append(random.choice(moves)) for x in range(0,len(scramble)-1): if scramble[x] == scramble[x+1]: scramble[x] = random.choice(moves) for x in range(0,len(scramble)-1): if scramble[x] == "R" and scramble[x+1] == "L": scramble[x+1] = random.choice(moves) if scramble[x] == "U" and scramble[x+1]== "D": scramble[x+1] == random.choice(moves) if scramble[x] == "F" and scramble[x+1] == "B": scramble[x+1] == random.choice(moves) modifiers = ["","2","'"] for x in range(25): randy = random.randint(0,2) finascramble.append(scramble[x]+modifiers[randy]) return " ".join(finascramble) t = True while t == True: again = input() if again == "s": print() print(getscramble()) 之后,至少应等待浏览器指示页面已加载,这意味着您需要添加

IE.Document.getElementsByName("submitButton").Item(0).Click

然后,如果您愿意,还有额外的等待时间。

此外,您可以添加最大循环时间,然后循环直到设置了对象为止。没有超时的情况如下:

While IE.Busy Or IE.readyState < 4: DoEvents: Wend