Search code examples
vbaexcelautomationoffice-automationbrowser-automation

IE 9 not accepting SendKeys


I posted on IE 9 not accepting SendKeys to download a file, but this problem is separate enough from the answer I received to justify another question. My problem is that I can't get IE 9 to accept any of the SendKeys. I have attempted Page Down, Tab, all of the F# keys, and none of them work.

Here is the code I am using:

Dim ie As Object

'This creates the IE object
Sub initializeIE()
   'call this subprocedure to start internet explorer up
   Set ie = CreateObject("internetexplorer.application")
   pos = 1
End Sub

'Initialize the class object
Private Sub Class_Initialize()
   initializeIE
End Sub

Function followLinkByText(thetext As String) As Boolean
  'clicks the first link that has the specified text
  Dim alink As Variant

  'Loops through every anchor in html document until specified text is found
  ' then clicks the link
  For Each alink In ie.document.Links
     If alink.innerHTML = thetext Then
          alink.Click
          'waitForLoad
          Application.Wait Now + TimeValue("00:00:01")
          Application.SendKeys "{PGDN}", True
          Application.SendKeys "{PGUP}", True
          'I've also tried calling it without Application before it
          SendKeys "{F1}", True
          SendKeys "{F2}", True
          'Etc... Each of these not being received by IE 9

          followLinkByText = True
          Exit Function
      End If
  Next

End Function

I'm at a total loss because it seems like most forums or tutorials don't do anything different for IE 9. The IE object is created in a class module and initialized in the Class_Initialize sub. I am not sure if that helps any, but I really have no idea why this isn't working and any help on how to send keys to IE would be greatly appreciated.


Solution

  • This is actually a copy of my answer to this question, but it may still apply.

    Is the IE window active when you try your SendKeys? If not, this would explain it not working.

    To activate your window:

    At the beginning of your module, put this line of code:

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

    This will allow you to access the SetForegroundWindow function built into Windows.

    In your code, while interacting with your IE object, record the HWND for that window like so:

    Dim HWNDSrc As Long
    HWNDSrc = ie.HWND
    

    Then after you've loaded the page, use this to continue, then send your key actions:

    SetForegroundWindow HWNDSrc
    

    However, this may not be necessary, depending on how you are interacting with IE. In other words, if you don't need to see/touch the window (you do for SendKeys), you can still interact using the object in code.


    Now, I see you using Application.Wait after you click, but that does not guarantee the IE page has loaded. This function should help with that.

     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
    

    At the risk of being long-winded, I've updated your code with these suggestions...

    ' Added by Gaffi
    Public Declare Function SetForegroundWindow Lib "user32" (ByVal HWND As Long) As Long
    Dim HWNDSrc As Long
    
    Dim ie As Object
    
    
    'This creates the IE object
    Sub initializeIE()
       'call this subprocedure to start internet explorer up
       Set ie = CreateObject("internetexplorer.application")
    
    ' Added by Gaffi
       HWNDSrc = ie.HWND
    
       pos = 1
    End Sub
    
    'Initialize the class object
    Private Sub Class_Initialize()
       initializeIE
    End Sub
    
    Function followLinkByText(thetext As String) As Boolean
      'clicks the first link that has the specified text
      Dim alink As Variant
    
      'Loops through every anchor in html document until specified text is found
      ' then clicks the link
      For Each alink In ie.document.Links
         If alink.innerHTML = thetext Then
              alink.Click
              'waitForLoad
    
    ' Added by Gaffi
              WaitForIE ie, HWNDSrc, 1
              SetForegroundWindow HWNDSrc
    
              'Application.Wait Now + TimeValue("00:00:01")
              Application.SendKeys "{PGDN}", True
              Application.SendKeys "{PGUP}", True
              'I've also tried calling it without Application before it
              SendKeys "{F1}", True
              SendKeys "{F2}", True
              'Etc... Each of these not being received by IE 9
    
              followLinkByText = True
              Exit Function
          End If
      Next
    
    End Function