Edge closes automatically at the end of macro - selenium

While automating edge browser using selenium vba, the edge browser automatically closes when the macro end sub function is executed. Is there a way to control this action & edge does not close automatically?

So, to avoid quitting the browser, you need to set the instance of the driver on a global variable:
Private Assert As New Assert
Private driver As New Selenium.FirefoxDriver
Sub ProcMain()
driver.Get "http://stackoverflow.com"
Call ClickLogo
End Sub
Sub QuitDriver()
driver.Quit
End Sub
Sub ClickLogo()
driver.FindElementByCss("#hlogo").Click
End Sub
Or For Example for Edge
Dim driver as WebDriver
Sub Repsol()
Set driver = New EdgeDriver
With driver
.Start "edge"
.Get "https://login.repsol.com/es/Landing/AuthnPage?returnUrl=https://www.repsol.com/es_es/"
With .FindElementByClass("gigya-login-form")
.FindElementByClass("gigya-input-text").SendKeys "user" 'your user
.FindElementByClass("gigya-input-password").SendKeys "password" 'your password
.FindElementByClass("gigya-input-submit").submit
End With
Application.Wait Now + TimeSerial(0, 0, 10)
.Get "https://www.repsol.com/es_es/aplicaciones/SO/WebEESS/default.aspx?usuario="""
Application.Wait Now + TimeSerial(0, 0, 10)
.Get "https://www.repsol.com/SO/WebEESS/Pages/Carburantes/PeticionCarburante/Peticion.aspx"
With .FindElementByClass("tablaContenedora")
.FindElementById("ctl00_zona1_grdwCarburantes_ctl02_lbltxtCantidad").SendKeys [B7]
End With
End With
End Sub

Related

Handle HTMLElement events in VBA

I use SHDocVw.InternetExplorer to show in powerpoint a local html file to the user. The file contains a form with a submit button and I would like to run my vba function when the button is clicked. I did the following to handle the onQuit-event of the InternetExplorer.
Class module "CIE"
Public WithEvents ie As SHDocVw.InternetExplorer
Private Sub ie_onQuit()
Debug.Print "onQuit was fired"
End Sub
Module code
Option Explicit
Public curCIE As CIE
Sub open_ie()
Dim CIEobj As CIE
Set CIEobj = New CIE
Dim ie As SHDocVw.InternetExplorer
Set ie = New SHDocVw.InternetExplorer
ie.Visible = True
ie.Navigate "C:\search.html"
Do While ie.Busy Or ie.readyState <> 4
DoEvents
Loop
Set CIEobj.ie = ie
Set curCIE = CIEobj
End Sub
I actually want to handle the onclick event of
curCIE.ie.Document.getElementsByTagName("button").Item(0)
but I do not know how to proceed.
You could add reference to MSHTML, then make your class module this way:
Public WithEvents ie As SHDocVw.InternetExplorer
Private WithEvents button As MSHTML.HTMLButtonElement
Public Sub LoadButton()
Set button = ie.document.getElementsByTagName("button").Item(0)
End Sub
Private Function button_onclick() As Boolean
'do what you want here
End Function
Private Sub ie_onQuit()
Debug.Print "onQuit was fired"
End Sub
And then, in the other module, add this statement after setting CIEobj.ie property:
CIEobj.LoadButton

Selenium VBA test case as a Function

I am trying do divide my test cases as a function in Selenium VBA using Excel. My first step is to login. I made login as a function for example
Public Sub test()
'my main program is here
'First step login
Login()
End sub
Function Login()
' Open Firefox command
' my commands here
'
End function
what happens is whenever I call Login() and when the function ends, It Closes the browser(in this case Mozilla firefox).
The browser is automatically disposed once the variable of the driver is out of scope. For further information, I invite you to have a look at the official documentation: https://support.microsoft.com/en-gb/kb/141693
Here is an example with a local instance of the driver:
Private Assert As New Assert
Sub Main()
Dim drv As New Selenium.FirefoxDriver
drv.Get "http://stackoverflow.com"
Call ClickLogo(drv)
drv.Quit
End Sub
Sub ClickLogo(drv As WebDriver)
drv.FindElementByCss("#hlogo").Click
End Sub
And another example with a global instance of the driver:
Private Assert As New Assert
Private drv As New Selenium.FirefoxDriver
Sub ProcMain()
drv.Get "http://stackoverflow.com"
Call ClickLogo
drv.Quit
End Sub
Sub ClickLogo()
drv.FindElementByCss("#hlogo").Click
End Sub
To get the latest version in date working with the above examples:
https://github.com/florentbr/SeleniumBasic/releases/latest
Dim your selenium webdriver before the start of your sub, this will allow the webdriver instance to run outside of the 'scope' of your main sub, then use driver.quit to kill the instance at the end of your program

Do Action if user returns to Excel from another Application

I have an Excel workbook that has links to a webpage. The user can click on the links, which minimize the Excel window and open their browser. When they are done with the site, they minimize or close their browser, which returns them to Excel (as it was their previous active window).
I would like VBA to take an action (update a table) when the user is returned to Excel.
I've looked at the Workbook_WindowActivate event, but this only works if you are moving from one Excel Workbook to another within the Excel Application.
Maybe I could use Application.name or the Windows function GetActiveWindow somehow but I am not sure how best to do this.
Any ideas? Thanks!
You want to add an event handler for Workbook_SheetFollowHyperlink. You can then use the code below. This just checks to see if the webpage has focus. the ' DO EVENTS ' is where you would add your code and then exit the sub
'********************* References used
'* Microsoft Shell Controls An Automation : shell32.dll*
'* Microsoft HTML Objects Library: MSHTML.dll expand ยป *
'* Microsoft Internet Controls: IEFRAME.dll *
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
Dim ie As InternetExplorer 'IE window variable
Dim sUrl 'url of the webpage
Dim dt As Date 'timer
'set the url to look for
sUrl = Target.Address
'set initial timeout period *used instead of browser ready due to page redirection.
'you should also check the browser ready status
dt = DateAdd("s", 5, DateTime.Now)
Do While dt > DateTime.Now
DoEvents
Loop
'reset the timeout period to allow time to view and select
dt = DateAdd("s", 30, DateTime.Now)
Dim shShell As New Shell ' windows shell variable
'continue loop until we hit the timeout or the webpage no longer has focus
Do While dt > DateTime.Now
'Loop through all the IE windows
For Each ie In shShell.Windows
'check to see if the URL's match
If InStr(ie.LocationURL, sUrl) Then
Dim hDoc As HTMLDocument
'get the webpage document
Set hDoc = ie.document
'check to see if it has focus
If Not hDoc.hasFocus Then
ThisWorkbook.Activate
'''''''''''''
' DO EVENTS '
'''''''''''''
Exit Sub
End If
Set hDoc = Nothing
End If
Next ie
Loop
End Sub
Here's what I've ended up doing. I borrowed quite a bit from this post: How to make a macro which executes periodically in Excel?
When the user clicks on a hyperlink, the code starts periodically checking whether Excel is their active window. I've found that the GetActiveWindow function returns zero if the user is not in the Excel application and some positive number if they are. If the code finds that the user returned to Excel from a different window (the previous check found that they were in a different window and the current one finds they are in Excel) then my table gets updated and the timer stops checking for the active window.
Doing it this way has the advantage of working for any web browser.
Option Explicit
Dim ExcelIsActive As Boolean
Private Declare Function GetActiveWindow Lib "user32" () As Long
Dim m_dtNextTime As Date
Dim m_dtInterval As Date
Dim DisableFlag As Boolean
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
Call start
End Sub
Public Sub Enable(Interval As Date)
Call Disable
m_dtInterval = Interval
Call starttimer
End Sub
Private Sub starttimer()
m_dtNextTime = Now + m_dtInterval
Application.OnTime m_dtNextTime, "TestActive"
End Sub
Public Sub TestActive()
If GetActiveWindow > 0 Then
If ExcelIsActive = False Then
ExcelIsActive = True
Call RefreshQuery
End If
Else
ExcelIsActive = False
End If
If Not DisableFlag Then
Call starttimer
Else
Call Disable
End If
End Sub
Public Sub Disable()
Dim dtZero As Date
If m_dtNextTime <> dtZero Then
' Stop timer if it is running
On Error Resume Next
Application.OnTime m_dtNextTime, "TestActive", , False
On Error GoTo 0
m_dtNextTime = dtZero
End If
m_dtInterval = dtZero
End Sub
Sub start()
'Start the timer
DisableFlag = False
ExcelIsActive = True
'Sets the interval to be three seconds
Call Enable(#12:00:03 AM#)
End Sub
Public Sub RefreshQuery()
'I do my stuff here
'Stop the timer until the next time the user launches the browser
DisableFlag = True
End Sub

taking control of an open browser instance

Set Browser = New SHDocVw.InternetExplorer
Once you create a new browser instance, how do you refer to that instance, instead of closing and reopening, say If I activate Excel window, then I want to activate back to the browser, how is this done?
I looked into
AppActivate "Windows Internet Explorer"
But If I have more than one window open, that wont work right, I dont think
I think you mean:
Option Explicit
Public browser As SHDocVw.InternetExplorer
Sub NavigateTo()
Set browser = New SHDocVw.InternetExplorer
browser.Visible = True
browser.Navigate "http://stackoverflow.com"
End Sub
In other words, declare the browser variable at module level so it remains available.
You can also capture an instance like so:
Sub getIE()
Dim sh As Object, oWin As Object, IE As Object
Set sh = CreateObject("Shell.Application")
For Each oWin In sh.Windows
If TypeName(oWin.Document) = "HTMLDocument" Then
Set IE = oWin
Exit For
End If
Next
Debug.Print IE.Document.url
End Sub

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.
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