单击按钮或使用 VBA 执行 JavaScript 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3247391/
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-08-23 03:51:51  来源:igfitidea点击:

Click button or execute JavaScript function with VBA

javascriptvbaexcel-vbaexcel

提问by Michael

I'm trying to get my VBA routine to interact with a page that uses JavaScript, and have been successful in the past. After a recent update, it no longer works. At this point I need to either A) programmatically click a button or B) execute the function the button calls. The tricky part is that the button has no declared name. There are others on the sheet declared in the source code with names, and I can interact with them just fine. Here's the html code from the page source:

我试图让我的 VBA 例程与使用 JavaScript 的页面进行交互,并且在过去取得了成功。最近更新后,它不再有效。此时,我需要 A) 以编程方式单击按钮或 B) 执行按钮调用的函数。棘手的部分是按钮没有声明名称。在源代码中声明的工作表上还有其他人的名字,我可以很好地与他们互动。这是页面源代码中的 html 代码:

<input type="button" class="buttonForm" value='Run Report' onclick="exportData(workOrderSearchForm)"/>

As you can see, it does not declare a name for the button. In the past, the following has worked:

如您所见,它没有为按钮声明名称。过去,以下方法有效:

Set ie = CreateObject("InternetExplorer.application")
ie.document.all(79).Click

With "79" being the index of the item number. It now appears that the button has been changed to item "81", but simply putting in:

其中“79”是项目编号的索引。现在看来按钮已更改为项目“81”,但只需输入:

ie.document.all(81).Click

is not working for some reason. I know the function I want to execute: exportData(workOrderSearchForm), but don't know how to do so outside of using the "click" method.

由于某种原因无法正常工作。我知道我要执行的函数:exportData(workOrderSearchForm),但不知道如何在使用“click”方法之外执行此操作。

I've looked for some decent documentation regarding the IE application object, but can't seem to find a good source. Is there a way to execute the function?

我已经寻找了一些关于 IE 应用程序对象的不错的文档,但似乎找不到一个好的来源。有没有办法执行该功能?

回答by Arun

Try this:

尝试这个:

Dim CurrentWindow As HTMLWindowProxy: Set CurrentWindow = ie.Document.parentWindow
Call CurrentWindow.execScript("exportData(workOrderSearchForm)")

But first you will need to include Microsoft HTML Object Library under References (Tools>References)

但首先您需要在参考(工具>参考)下包含 Microsoft HTML 对象库

回答by MikeD

You can cycle thru all input tags and identify the relevant one by inspecting "the most identifying" attribute (id, name, type, innerHTML, ...whatever). Here's a Sub() I use in an Excel sheet which automatically logs on to a web site

您可以循环浏览所有输入标签并通过检查“最具识别性”的属性(id、名称、类型、innerHTML 等)来识别相关的标签。这是我在 Excel 工作表中使用的 Sub(),它会自动登录到网站

Sub FormAction(Doc As MSHTML.HTMLDocument, ByVal Tag As String, ByVal Attrib As String, ByVal Match As String, ByVal Action As String)
Dim ECol As MSHTML.IHTMLElementCollection
Dim IFld As MSHTML.IHTMLElement
Dim Tmp As String

    Set ECol = Doc.getElementsByTagName(Tag)
    For Each IFld In ECol                                         ' cycle thru all <[tag]> elements
        If VarType(IFld.getAttribute(Attrib)) <> vbNull Then      ' does it contain the attribute
            If Left(IFld.getAttribute(Attrib), Len(Match)) = Match Then
                If Action = "/C/" Then
                    IFld.Click
                Else
                    IFld.setAttribute "value", Action
                End If
                Exit Sub
            End If
        End If
    Next
End Sub

The function takes following parameters:

该函数采用以下参数:

  • Doc .... the HTML DOM object
  • Tag .... the tag you want to work on (usually input, image, a, ...)
  • Attrib .... the attribute whose value you want to match
  • Match .... the matching value for the attribute
  • Action ..... if "/C/" the .Click() action is performed on the matched tag, else the action value is put into the value attribute of the tag
  • Doc .... HTML DOM 对象
  • Tag .... 你想要处理的标签(通常是 input、image、a、...)
  • Attrib .... 要匹配其值的属性
  • Match .... 属性的匹配值
  • Action ..... 如果 "/C/" .Click() 动作在匹配的标签上执行,否则动作值被放入标签的 value 属性

If you want to hook on any attribute containing JavaScript code (like "onclick") don't forget that the code you see in the HTML source is embeded in an anonymous function, like

如果您想挂钩任何包含 JavaScript 代码的属性(例如“onclick”),请不要忘记您在 HTML 源代码中看到的代码嵌入在一个匿名函数中,例如

function anonymous()
{
onclick="exportData(workOrderSearchForm)";
}

You need to consider this by using an Instr() function or similar, if you want to hook on e.g. "exportData(workOrder" .

如果您想挂钩例如 "exportData(workOrder" ,则需要使用 Instr() 函数或类似函数来考虑这一点。

Also very important: give enough time for the page to navigate to and for the DOM object to be loaded. I notice in my company that once pages are changed the loading times sometimes raise drastically.

同样非常重要的是:为页面导航和加载 DOM 对象留出足够的时间。我注意到在我的公司,一旦页面更改,加载时间有时会急剧增加。

I have good success by this:

我在这方面取得了很好的成功:

Sub MyMainSub()
Dim Browser As SHDocVw.InternetExplorer
Dim HTMLDoc As MSHTML.HTMLDocument
' my other Dim's

    ' start browser
    Set Browser = New SHDocVw.InternetExplorer
    Browser.navigate "http://www.whatever.com"
    WaitForBrowser Browser, 5           ' wait for browser, but not more than 5 sec

    ' gain control over DOM object
    Set HTMLDoc = Browser.document
    WaitForBrowser Browser, 5           ' wait for browser, but not more than 5 sec

    ' do actions
    ' FormAction HTMLDoc, w, x, y, z

End Sub


Sub WaitForBrowser(Browser As SHDocVw.InternetExplorer, Optional TimeOut As Single = 10)
Dim MyTime As Single

    MyTime = Timer                   ' seconds since midnight
    Do While Browser.Busy Or (Timer <= MyTime + TimeOut)
        DoEvents                     ' go do something else
    Loop

    If Browser.Busy Then
        MsgBox "I waited for " & Timer - MyTime & " seconds, but browser still busy" & vbCrLf & _
               "exititing Login sequence now"
        End
    End If
End Sub

Hope this is inspiring enough for you to create your solution.

希望这足以启发您创建解决方案。

Good luck MikeD

祝你好运迈克

回答by SLaks

Like this:

像这样:

ie.window.exportData(ie.document.forms.workOrderSearchForm)