VBA automation with Edge IE mode

J710 11 Reputation points
2022-04-28T01:47:11.177+00:00

I have been using VBA to automate IE in the past and I understand that IE with be demised soon. I heard that ActiveX can be used in Edge IE mode until 2029. May I know how can I do so? Do I have to change any of my old code? My code which worked with IE will only open IE browser and will not interact with Edge IE mode. Do I have to amend anything to tell VBA to interact with Edge IE mode instead of IE? My computer is in Win10 20H2 and KB5011487 have been installed to it.

My code is something like this:
‘opened the XXXX website manually before running the code
‘Search for tab named XXXX
Set ieApp = FindIEObject(“XXXXX”)
‘Send the text to the yyy text box
ieApp.document.all.Item(“yyy”).Value = ThisWorkbook.Sheets(“Sheet1”).Range(“A” & 1)
‘Press click
ieApp.document.getElementById(“zzz”).Click

Microsoft Edge
Microsoft Edge
A Microsoft cross-platform web browser that provides privacy, learning, and accessibility tools.
2,151 questions
{count} votes

8 answers

Sort by: Most helpful
  1. Kelvin Yeung 11 Reputation points
    2022-05-09T07:42:20.83+00:00

    Automation on Edge Browser Webpage : Win API to Retrieve HTMLDocuments of Webpages in Existing Edge Browser Windows | By Kelvin Yeung | May 9, 2022 | VBA Programming – Win API & Edge Browser Automation

    I had been using IE and Internet Object Model (IOM) to achieve automation with internal web-based systems in my works at bank. Since the announcement that IE will be no longer supported by Microsoft at 15 June 2022, I started to look for possible alternative solutions on the internet. After investigation, I found that there are two solutions to achieve automation on Edge browser : 1) SeleniumBasic or 2) Win API. Though SelenimBasic seems to be the mainstream suggestion at forums, Win API can be regarded as better solution in several different ways, especially for my own situations.

    Pros of Win API Solution :

    • No need installation and regular update of Edge driver.
    • Able to automate with multiple existing Edge browser windows (which have been opened before program start).
    • Most of codes in existing IOM solution can be preserved and re-applied. It is because both solutions of IOM and Win API should use HTML Document Object Model (DOM) at last to achieve automation on webpage. The difference is on the way to find browser and attain HTMLDocument from browser.

    Cons of Win API Solution :

    • We can automate with “webpage” on Edge browser but not the “Edge browser” itself. It is not like IOM and SeleniumBasic that can control web browser. For this, I use Shell function and DOS commands to achieve automation of opening and closing Edge browser.
    • The webpage has to be opened in IE mode at Edge browser which means this solution is subject to Microsoft’s future direction on IE mode of Edge browser.

    Sharing on my experiences to use Win API on Edge browser webpage automation :

    1. Place the following codes in a new blank module. I name this module as “MsEdge” usually. The codes in this module are no need to modify for usage. You can directly use the codes even if you don’t know much about Win API. Public lngProcessID_Close As Long 'Part 1 --- Locate IES Private strHwndIES As String Private lngHwndIndex As Long Private Declare PtrSafe Function EnumWindows Lib "user32" ( _ ByVal lpEnumFunc As LongPtr, ByVal lParam As Long) As Long Private Declare PtrSafe Function EnumChildWindows Lib "user32" ( _ ByVal hWndParent As LongPtr, ByVal lpEnumFunc As LongPtr, ByVal lParam As Long) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _ ByVal hWnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long 'Part 2 --- Get HTMLDocument from IES Private Const SMTO_ABORTIFHUNG = &H2 Private Const GUID_IHTMLDocument2 = "{332C4425-26CB-11D0-B483-00C04FD90119}" Private Declare PtrSafe Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" ( _ ByVal lpString As String) As Long Private Declare PtrSafe Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" ( _ ByVal hWnd As Long, _ ByVal msg As Long, _ ByVal wParam As Long, _ lParam As Any, _ ByVal fuFlags As Long, _ ByVal uTimeout As Long, _ lpdwResult As Long) As Long Private Declare PtrSafe Function IIDFromString Lib "ole32" ( _ lpsz As Any, lpiid As Any) As Long Private Declare PtrSafe Function ObjectFromLresult Lib "oleacc" ( _ ByVal lResult As Long, _ riid As Any, _ ByVal wParam As Long, _ ppvObject As Any) As Long 'Part 3 --- Check Process Name Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" ( _ ByVal hWnd As Long, lpdwProcessId As Long) As Long Public Function findEdgeDOM(Title As String, URL As String) As HTMLDocument
       'Find criteria-hitting Edge page in IE mode
      
       Dim hwndIES As Long
      
       Do
      
           hwndIES = enumHwndIES
      
           If hwndIES Then
      
               Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES)
      
               If Not findEdgeDOM Is Nothing Then
      
                   If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then
      
                       Do
      
                           hwndIES = enumHwndIES
      
                       Loop While hwndIES
      
                       Exit Function
      
                   Else
      
                       Set findEdgeDOM = Nothing
      
                   End If
      
               End If
      
           End If
      
       Loop While hwndIES
      
      End Function Public Function enumHwndIES() As Long
       'Get all hwnds of IES
      
       If Len(strHwndIES) = 0 Then
      
           EnumWindows AddressOf EnumWindowsProc, 0
      
           lngHwndIndex = 0
      
       End If
      
       'Exit function when overflow
      
       If lngHwndIndex + 1 > (Len(strHwndIES) - Len(Replace(strHwndIES, ",", ""))) Then
      
           enumHwndIES = 0
      
           strHwndIES = ""
      
           Exit Function
      
       End If
      
       'Return IES hwnd one by one
      
       enumHwndIES = CLng(Split(Left(strHwndIES, Len(strHwndIES) - 1), ",")(lngHwndIndex))
      
       lngHwndIndex = lngHwndIndex + 1
      
      End Function Private Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
       Dim lngProcessID As Long
      
       GetWindowThreadProcessId hWnd, lngProcessID
      
       EnumChildWindows hWnd, AddressOf EnumChildProc, lngProcessID
      
       EnumWindowsProc = True
      
      End Function Public Function EnumChildProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
       Dim strTargetClass As String, strClassName As String
      
       strTargetClass = "Internet Explorer_Server"
      
       strClassName = getClass(hWnd)
      
       If strClassName = strTargetClass Then
      
           If GetObject("winmgmts:").ExecQuery("Select Name from Win32_Process WHERE ProcessId='" & lParam & "' AND Name='msedge.exe'").Count Then
      
               strHwndIES = strHwndIES & hWnd & ","
      
               lngProcessID_Close = lParam
      
               EnumChildProc = False
      
               Exit Function
      
           End If
      
       End If
      
       EnumChildProc = True
      
      End Function Private Function getClass(hWnd As LongPtr) As String
       Dim strClassName As String
      
       Dim lngRetLen As Long
      
      
       strClassName = Space(255)
      
       lngRetLen = GetClassName(hWnd, strClassName, Len(strClassName))
      
       getClass = Left(strClassName, lngRetLen)
      
      End Function Public Function getHTMLDocumentFromIES(ByVal hWnd As Long) As Object
       Dim iid(0 To 3) As Long
      
       Dim lMsg As Long, lRes As Long
      
       lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT")
      
       SendMessageTimeout hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes
      
       If lRes Then
      
           IIDFromString StrPtr(GUID_IHTMLDocument2), iid(0)
      
           ObjectFromLresult lRes, iid(0), 0, getHTMLDocumentFromIES
      
       End If
      
      End Function Public Sub closeEdge(Title As String, URL As String)
       'Close a Edge browser (the last one in EnumWindows order) with criteria-hitting webpage
      
       lngProcessID_Close = 0
      
       Dim findEdgeDOM As Object
      
       Dim hwndIES As Long
      
       Do
      
           hwndIES = enumHwndIES
      
           If hwndIES Then
      
               Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES)
      
               If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then
      
                   Shell "TaskKill /pid " & lngProcessID_Close
      
                   Do
      
                       hwndIES = enumHwndIES
      
                   Loop While hwndIES
      
                   Exit Sub
      
               End If
      
           End If
      
       Loop While hwndIES
      
      End Sub

    1. Apply the functions in “MsEdge” module. There are a few application examples for you. Suggest to place and test below codes at another module: Sub findEdgeDOM_DemoProc()
       'Demo Proc : Use findEdgeDOM Function to get DOM of specific Edge webpage by Title AND URL
      
       'Dim docHTML As MSHTML.HTMLDocument     '--- Early Binding
      
       Dim docHTML As Object                   '--- Late Binding
      
       Set docHTML = findEdgeDOM("Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here")
       ‘You can fill just one argument with either part of webpage title or URL as keyword to search for the target browser and leave another one blank (“”). If you provide both title and URL, the funcitons return DOM of the only browser that meets both criteria.
      
       If Not docHTML Is Nothing Then Debug.Print docHTML.Title, docHTML.URL
      
      End Sub Sub goEdge()
       'Go through every Edge webpage (opened in IE mode) and print out hwndIES, webpage Title & webpage URL
      
       Dim hwndIES As Long
      
       'Dim docHTML As MSHTML.HTMLDocument     '--- Early Binding
      
       Dim docHTML As Object                   '--- Late Binding
      
       Do
      
           hwndIES = enumHwndIES
      
           If hwndIES Then
      
               Set docHTML = getHTMLDocumentFromIES(hwndIES)
      
               Debug.Print hwndIES, docHTML.Title, docHTML.URL
      
           Else
      
               Debug.Print "Procedure End"
      
           End If
      
       Loop While hwndIES
      
      End Sub Sub openEdgeByURL_DemoProc()
       openEdgeByURL "Input Webpage URL Here"
      
      End Sub Public Sub openEdgeByURL(URL As String)
       'Please change the path to your msedge.exe location in your PC
      
       Shell "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe -url " & URL, vbNormalFocus
      
      End Sub Sub closeEdge_DemoProc()
       closeEdge "Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here"
      
      End Sub
    1 person found this answer helpful.

  2. Reza-Ameri 16,836 Reputation points
    2022-04-28T13:56:02.75+00:00

    In general, it is recommended to move from Active X and everything related to the Internet Explorer and re-design your application with modern web standards or as Microsoft Edge Extensions.
    Internet Explorer Mode is just for backward compatibility and to give more time to developers to move into Microsoft Edge.


  3. Yu Zhou-MSFT 12,141 Reputation points Microsoft Vendor
    2022-04-29T03:23:48.32+00:00

    Hi @J710

    If Selenium is not an option, I think you can't automate with Edge IE mode.

    The only way to automate with Edge IE mode is using IEDriver. You can't do it with only VBA. You need to:

    1. Define InternetExplorerOptions with additional properties that point to the Microsoft Edge browser.
    2. Start an instance of InternetExplorerDriver and pass it InternetExplorerOptions. IEDriver launches Microsoft Edge and then loads your web content in IE mode.

    For more information, you can refer to this doc.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Regards,
    Yu Zhou

    0 comments No comments

  4. AHRION GALLEGOS 16 Reputation points
    2022-05-29T19:40:54.87+00:00

    This works Win 10, 64-bit. For reference, I changed cosmetically a few things (for my eyes), simply added PtrSafe and LongPtr only where necessary, and added .dll, as sometimes 64-bit recognizes original 32-bit libraries funky:

    ' [ Prefix --- Declare global variables ]
    
    Global lngProcessID_Close As Long
    
    ' [ Part 1 --- Locate IES ]
    
    Public strHwndIES As String
    
    Public lngHwndIndex As Long
    
    Public Declare PtrSafe Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As LongPtr, ByVal lParam As Long) As Long
    
    Public Declare PtrSafe Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As Long, ByVal lpEnumFunc As LongPtr, ByVal lParam As Long) As Long
    
    Public Declare PtrSafe Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    
    ' [ Part 2 --- Get HTMLDocument from IES ]
    
    Public Const SMTO_ABORTIFHUNG = &H2
    
    Public Const GUID_IHTMLDocument2 = "{332C4425-26CB-11D0-B483-00C04FD90119}"
    
    Public Declare PtrSafe Function RegisterWindowMessage Lib "user32.dll" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
    
    Public Declare PtrSafe Function SendMessageTimeout Lib "user32.dll" Alias "SendMessageTimeoutA" ( _
        ByVal hWnd As Long, _
        ByVal msg As Long, _
        ByVal wParam As Long, _
        lParam As Any, _
        ByVal fuFlags As Long, _
        ByVal uTimeout As Long, _
        lpdwResult As Long) As Long
    
    Public Declare PtrSafe Function IIDFromString Lib "ole32.dll" (lpsz As Any, lpiid As Any) As Long
    
    Public Declare PtrSafe Function ObjectFromLresult Lib "oleacc.dll" (ByVal lResult As Long, riid As Any, ByVal wParam As Long, ppvObject As Any) As Long
    
    ' [ Part 3 --- Check Process Name ]
    
    Public Declare PtrSafe Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    

  5. Mateusz Kornet 1 Reputation point
    2022-06-02T20:56:00.077+00:00

    Thanks Kelvin!

    Right now I'm using IE via VBA
    I spawn one browser window. Log in to the web page and keep it opened.
    Then I follow about hundred links from that page and get part of HTML. I open these links in separate windows by using:

    Dim appIE As InternetExplorerMedium
    

    to keep the session.
    Is it possibe to achieve the same with your code?

    Humble thanks.