VBA与互联网浏览器的互动

时间:2012-07-25 15:10:23

标签: internet-explorer vba excel-vba automation sendkeys

我正在构建的宏从Excel电子表格中获取名称,打开Internet Explorer,然后搜索在线目录。在搜索目录之后,它会提取一个包含管理器名称的Java表单。我可以手动选项卡到管理器名称,右键单击,复制快捷方式,然后将其发布回电子表格。但是,我遇到了一致标签和复制快捷方式的问题。

  1. 有没有一种简单的方法可以将焦点带回IE窗口?
  2. 如何在不手动点击快捷方式的情况下复制快捷方式?
  3. 代码:

    Sub Macro1()
    '
    Dim ie As Object
    Set ie = CreateObject("internetexplorer.application")
    
    ie.Visible = True
    ie.navigate "****url****"
    
    While ie.busy
        DoEvents
    Wend
    
    ie.document.getElementById("SSOID").Value = "Z19516732"
    ie.document.getElementById("Advanced").Checked = False
    ie.document.all("Search").Click
    
    'this loop is to slow the macro as the java form is filled from the search
    For i = 1 To 400000000  
        i = i + 1
    Next i
    
    'ie.Object.Activate
    ie.document.getElementById("Advanced").Checked = False
    ie.document.getElementById("SSOID").Focus
    Application.SendKeys "{TAB 6}" ', True
    
    'bring up the control menu/right click
    Application.SendKeys "+{F10}"
    
    'copy shortcut is 8 items down on the list
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    Application.SendKeys "{DOWN}"
    
    'enter was not working so the shortcut for the menu is 't'
    'SendKeys "{ENTER}"
    Application.SendKeys "{t}"
    
    Windows("Book21").Activate
    Range("A1").Select
    ActiveSheet.Paste
    
    End Sub
    

1 个答案:

答案 0 :(得分:8)

在模块的开头,输入以下代码:

Public Declare Function SetForegroundWindow Lib "user32" (ByVal HWND As Long) As Long

这称为Declare Statement,允许您访问Windows内置的SetForegroundWindow函数。此函数位于Windows系统的user32 DLL中。实际上,VBA可以通过这种方式访问​​多个DLL中的许多其他函数(有关更多示例,请参阅链接)。

在您的代码中,在与IE对象进行交互时,将HWNDhandle记录到该窗口中),如下所示:

Dim HWNDSrc As Long
HWNDSrc = ie.HWND

然后,在与Java交互之后,使用它继续:

SetForegroundWindow HWNDSrc

这告诉Windows系统将HWND标识的窗口设置为前景窗口(顾名思义)。

但是,这可能没有必要,具体取决于您与IE的交互方式。换句话说,如果您不需要查看/触摸窗口,您仍然可以使用该代码中的对象进行交互。

有一些方法可以使用GetElementById()GetElementsByTagName()see here for more info)等代码获取您要查找的快捷方式,但这取决于源的创建方式。例如如果您知道HTML源代码,那么<a href="...>链接应该相对容易拉动。


第二次检查你的代码后,我注意到你使用循环来“减慢”宏。我有一个功能,我一直使用自己的类似方法。希望这有助于您完成所需的工作。我已经从我原来的代码中修改了我的代码,因为我有其他细节不适用于您的情况。如果有任何错误,我可以根据需要进行调整。

Public Sub WaitForIE(myIEwindow As InternetExplorer, HWND As Long, WaitTime As Integer)

    ' Add pauses/waits so that window action can actually
    ' begin AND finish before trying to read from myIEWindow.

    ' myIEWindow is the IE object currently in use
    ' HWND is the HWND for myIEWindow
    ' The above two variables are both used for redundancy/failsafe purposes.
    ' WaitTime is the amount of time (in seconds) to wait at each step below. 
    ' This is variablized because some pages are known to take longer than 
    ' others to load, and some pages with frames may be partially loaded,
    ' which can incorrectly return an READYSTATE_COMPLETE status, etc.

    Dim OpenIETitle As SHDocVw.InternetExplorer

    Application.Wait DateAdd("s", WaitTime, Now())

    Do Until myIEwindow.ReadyState = READYSTATE_COMPLETE
        ' Wait until IE is done loading page and/or user actions are done.
    Loop

    Application.Wait DateAdd("s", WaitTime, Now())

    While myIEwindow.Busy
        DoEvents  ' Wait until IE is done loading page and/or user actions are done.
    Wend

    On Error Resume Next
    ' Make sure our window still exists and was not closed for some reason...
    For Each OpenIETitle In objShellWindows
        If OpenIETitle.HWND = HWND Then
            If Err.Number = 0 Then
                Set myIEwindow = OpenIETitle
                Exit For
            Else
                Err.Clear
            End If
        End If
    Next OpenIETitle
    On Error GoTo 0

End Sub