I am looking for a way to control Zoom in chrome with selenium.
I have tried
driver.ExecuteScript ("document.body.style.zoom='75%'")
This zoom in the actual page, NOT like ctrl & -
driver.ExecuteScript "chrome.settingsPrivate.setDefaultZoom(1.5)"
This wont complie
I have no problems with eg. CTRL+a
(for selecting evrything
driver.FindElementByTag("body").SendKeys Keys.Control, "a"
but it dosn't work for SendKeys Keys.Control, Subtract
The second command doesn't compile because before using it you have to go to the settings page
driver.Get('chrome://settings/')
driver.ExecuteScript('chrome.settingsPrivate.setDefaultZoom(1.5);')
Login Zoom and open multiple pages.
First- dont Zoom before login, it wont click the BTN, heres my final code
Dim driver As New Selenium.ChromeDriver ' defines outside sub to prevent Crome to close at end of sub
sub loginOpen()
driver.start "chrome", "" ' new driver instance
Dim sURL As String
Dim rng As Range
Dim First As Boolean
Dim i As Variant
First = True
Set rng = Selection
With driver
For Each i In rng
If First Then
.Get sURL ' could also just be the login page
.Window.SetSize 1400, 768
First = False
' if we need to login
If Left(.Url, Len(sURL)) <> sURL Or .Url = "" Then
.FindElementByName("tbusername").SendKeys ("user")
.FindElementByName("tbpassword").SendKeys ("password")
.FindElementById("btnlogin").Click
.Get ("chrome://settings/")
.ExecuteScript ("chrome.settingsPrivate.setDefaultZoom(0.75);")
.Get sURL
End If
Else
.ExecuteScript "window.open(arguments[0])", sURL
.SwitchToNextWindow
End If
Next
End With
End Sub
Related
I would like to run my VBA macro on a specific internet explorer page that I have already opened and logged into .
This is because I have to login to my account and bypass the captcha code first.
I have to send this extremely repetitive message to over a couple hundred people over the course of the year.
Problem with the following is that I am opening up a brand new page and I wont be able to bypass the captcha.
Dim IE As InternetExplorer
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate ("website")
IE.Visible = True
End Sub
Solution
Sub TestGetIE()
Dim IE As Object
'GetIE runs the Functoin we have created below
Set IE = GetIE("website opened in IE here ")
WaitFor IE
end sub
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
'Loop through all the opened internet explorer pages
sURL = ""
'Loops through all the pages opened on internet explorer
'Then we will tell our macro to work on that page
sURL = o.LocationURL
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function
From your description, I understand that you want user interaction to fill the captcha and then want to continue to automate the same page.
I suggest you for both steps try to use 2 different modules and use the same IE object in both modules.
You can create a global IE object which you can use in both modules.
Then for the login part execute the first module.
After that user will fill the captcha manually.
Then execute the second module to automate the rest of the page.
Sample code:
Public ie As Object
Sub login()
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
ie.navigate "Your_web_site_URL_here..."
Do While ie.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
ie.document.getElementById("uname").Value = "user1"
ie.document.getElementById("pswd").Value = "12345"
End Sub
Sub second_part()
ie.document.getElementById("email").Value = "user1#abc.com"
ie.document.getElementById("age").Value = "30"
End Sub
UserForm1 code:
Private Sub CommandButton1_Click()
Call Module1.login
End Sub
Private Sub CommandButton2_Click()
Call Module1.second_part
End Sub
Output:
Calling upon this function helped me solve it.
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
'Loop through all the opened internet explorer pages
sURL = ""
'Loops through all the pages opened on internet explorer
'Then we will tell our macro to work on that page
sURL = o.LocationURL
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function
One thing you could do is DoEvents until a certain Element is present on the page. Run your code to navigate to the website, then Do Until Element after captcha is present DoEvents. The code will loop until you are on logged into the website. I like using VBA SeleniumBasic ChromeDriver on GetHub. It makes web scraping way easier, and you do not need to use Internet Explorer.
I've got a macro which currently works but I'm trying to automate the final "quirk" that I have had to live with up till now. Basically it opens IE to a URL which then closes the window and spits back a download window and I have excel use SENDKEYS to download file.
I'm struggling to bring the download window to focus, currently my end users click on the DL window for sendkeys to work as expected.
I have read through the following and tried utilizing the code to no avail:
vbscript - Bring Internet Explorer Application window to front
VBA to Activate Internet Explorer Window
Bringing Internet Explorer window to foreground
Set Focus to Internet Explorer Object in Visual Basic
There a few things to note:
I can't download the file via batch as I need IE to pass along the credentials.
The file is not static, the URL runs a script on the backend and then presents the file back to end terminal
I can't have any requirement to "Enable Reference Library" on end users computers
The macro is as follows:
Public Sub DLFILE()
'This will load a webpage in IE
Dim i As Long
Dim URL As String
Dim ie As Object
Dim objElement As Object
Dim objCollection As Object
'Create InternetExplorer Object
Set ie = CreateObject("InternetExplorer.Application")
'Define URL
URL = "http://example.com/"
'Navigate to URL
ie.navigate URL
' Statusbar let's user know website is loading
Application.StatusBar = URL & " is loading. Please wait..."
'IE ReadyState = 4 signifies the webpage has loaded (the first loop is set to avoid inadvertently skipping over the second loop)
Do While ie.ReadyState = 4: DoEvents: Loop 'Do While
Application.Wait (Now() + TimeValue("00:00:04"))
SendKeys "{RIGHT}{RIGHT}{ENTER}{TAB}{TAB}{TAB}{TAB}{ENTER}"
'Do Until IE.ReadyState = 4: DoEvents: Loop 'Do Until
'Unload IE
Set ie = Nothing
Set objElement = Nothing
Set objCollection = Nothing
End Sub
Also note, this doesn't bring up the prompt in the bottom of the IE window, but closes that window and brings up the "Full Downloads Window" like below.
As the shortcut for the "View Downloads" window is Ctrl+J in IE so I think we can use sendkeys to click Ctrl+J to bring the window to the front.
Sample code:
Sub LOADIE()
Set ieA = CreateObject("InternetExplorer.Application")
ieA.Visible = True
ieA.navigate "https://www.bing.com/"
Do Until ieA.readyState = 4
DoEvents
Loop
Application.Wait (Now + TimeValue("00:00:03"))
Application.SendKeys "^{j}"
End Sub
Result:
What I ended up doing was using an ObjURL to open the IE instance and then a DLUrl which I opened after. This made a few important adjustments, it's similar to opening a second tab in IE which would close, but instead of using the "Downloads Window" it would use the prompt at the bottom of the IE Window. This allowed me to continue to control the IEObj as the original ObjURL was still open. I couldn't get excel VBA to consistently control the "Downloads Window", but I was able to get consistent results using the following snippets. Between the two adjustments I now have consistent results.
Public Declare Function SetForegroundWindow Lib "user32" (ByVal HWND As Long) As Long
And
'Bring IEObj to Focus
HWNDSrc = IEObj.HWND
SetForegroundWindow HWNDSrc
Full Sub:
Public Declare Function SetForegroundWindow Lib "user32" (ByVal HWND As Long) As Long
Public Sub DL_File_IE()
Dim DLUrl As String, ObjURL As String
Dim IEObj As Object, objElement As Object, objCollection As Object
Set IEObj = CreateObject("InternetExplorer.Application")
IEObj.Visible = True
ObjURL = "http://google.com"
DLUrl = "http://example.com/file
IEObj.navigate ObjURL
Do Until IEObj.readyState = 4
DoEvents
Loop
IEObj.navigate DLUrl
'Bring IEObj to Focus
HWNDSrc = IEObj.HWND
SetForegroundWindow HWNDSrc
Application.Wait (Now() + TimeValue("00:00:02"))
SendKeys "{TAB}{TAB}{ENTER}", True ' Select "Save" in DL Window
Application.Wait (Now() + TimeValue("00:00:02"))
SendKeys "%{f4}", True ' Alt + F4 = Close IEObj
'Unload IE
Set IEObj = Nothing
Set objElement = Nothing
Set objCollection = Nothing
End Sub
I'm using this code to grab the instance of Internet Explorer from word VBA and scraping some values from a webpage. I'm looping through 4 items (just in case, sometimes I've accidentally grabbed something called "Windows Explorer", which I have no idea what that is) to grab Internet Explorer. But before I begin scraping values, I want to make sure my tab name is "Overview - City". How can I test against the tab names?
Dim shellWins As ShellWindows, IE As InternetExplorer
Dim i As Long
Set shellWins = New ShellWindows
'Find Internet Explorer - if it can't find it, close the program
If shellWins.Count > 0 Then
For i = 0 To 3
On Error Resume Next
If shellWins.Item(i).Name = "Internet Explorer" Then
Set IE = shellWins.Item(i)
Exit For
End If
On Error GoTo 0
If i = 3 Then
MsgBox "Could not find Internet Explorer.", vbExclamation, "Error"
Exit Sub
End If
Next i
Else
MsgBox "Could not find Internet Explorer.", vbExclamation, "Error"
Exit Sub
End If
I tried following the guide here and used this bit to try and Debug.Print all the active tab names in IE once I had found it:
Dim IE_Tab As SHDocVw.InternetExplorer
Dim SH_Win As SHDocVw.ShellWindows
For each IE_Tab in SH_Win
Debug.Print IE_Tab.Name 'This returns nothing?
Next IE_Tab
But the immediate window returns blank with no error. What am I doing wrong?
Here is some code that should find a reference to the open Internet Explorer tab. It does this by looping through the Shell.Application.Windows collection. The function supports looking for just the WindowName, the URL and WindowName, and supports specifying the compare method or if you want to do a like match. I kept this code late bound, to avoid needing references.
The code is commented, somewhat, let me know if there are questions.
Code
Option Explicit
Private Function GetIEWindow(WindowName As String, _
ExactMatch As Boolean, _
Optional CompareMethod As VbCompareMethod = vbTextCompare, _
Optional URL As String) As Object
Dim Window As Object
Dim Windows As Object: Set Windows = CreateObject("Shell.Application").Windows
For Each Window In Windows
'Make sure the app is Internet Explorer. Shell Windows can include other apps
If InStr(1, Window.FullName, "IEXPLORE.EXE", vbTextCompare) > 0 Then
'Perform exact matches, where the title or url and title match exactly
If ExactMatch Then
If Len(URL) = 0 Then
If Window.LocationName = WindowName Then
Set GetIEWindow = Window
Exit Function
End If
Else
If Window.LocationName = WindowName And Window.LocationUrl = URL Then
Set GetIEWindow = Window
Exit Function
End If
End If
Else
'Otherwise do a In String match
If Len(URL) = 0 Then
If InStr(1, Window.LocationName, WindowName, CompareMethod) > 0 Then
Set GetIEWindow = Window
Exit Function
End If
Else
If InStr(1, Window.LocationName, WindowName, CompareMethod) > 0 And InStr(1, Window.LocationUrl, URL, CompareMethod) > 0 Then
Set GetIEWindow = Window
Exit Function
End If
End If
End If
End If
Next
End Function
Sub ExampleUsage()
Dim IE As Object: Set IE = GetIEWindow("exe", True)
If Not IE Is Nothing Then
Debug.Print "I found the IE window"
Else
Debug.Print "I didn't find the IE window"
End If
End Sub
The tab is just another window. You can use the GetWebPage function below to loop through the windows and get the URL you are looking for.
References are
Microsoft Internet Controls
Microsoft Shell Controls and Automation
Sub Example()
Dim ieWin As InternetExplorer
Set ieWin = CreateObject("InternetExplorer.Application")
With ieWin
.Navigate "https://www.google.com/"
.Visible = True
.Silent = True
End With
Set ieWin = GetWebPage("https://www.google.com/")
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Desc: The Function gets the Internet Explorer window that has the current
' URL from the sURL Parameter. The Function Timesout after 30 seconds
'Input parameters:
'String sURL - The URL to look for
'Output parameters:
'InternetExplorer ie - the Internet Explorer window holding the webpage
'Result: returns the the Internet Explorer window holding the webpage
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function GetWebPage(sUrl As String) As InternetExplorer
Dim winShell As Shell
Dim dt As Date
dt = DateAdd("s", 300, DateTime.Now)
Dim ie As InternetExplorer
Do While dt > DateTime.Now
Set winShell = New Shell
'loop through the windows and check the internet explorer windows
For Each ie In winShell.Windows
If ie.LocationURL = sUrl Then
Set GetWebPage = ie
Do While ie.Busy
DoEvents
Loop
Exit Do
Set winShell = Nothing
End If
Next ie
Set winShell = Nothing
DoEvents
Loop
End Function
I'm trying to simulate the interaction with Google through the IE app and going through the DOM to get the classes I need and all is fine, stepping though the code, except the .Click action which doesn't cause a crash but it doesn't do anything (page doesn't navigate) - Code and screenshot of HTML below:
Option Explicit
Private Sub Test_Automation()
Dim ie, doc, eInput, eButton, eButtons As Object
Dim sURL, sTest As String
Set ie = CreateObject("internetexplorer.application")
sURL = "https://www.google.co.uk/?gfe_rd=cr&ei=IpDvWK72LsjCaJCbjKAL&gws_rd=ssl"
sTest = "Test"
With ie
.Visible = True
.Navigate sURL
End With
Do While ie.Busy Or ie.readyState <> 4
DoEvents
Loop
Set doc = ie.document
Set eInput = doc.getElementByid("lst-ib")
Set eButtons = doc.getElementsByTagName("input")
eInput.Value = sTest
For Each eButton In eButtons
If (eButton.getattribute("name") = "btnK") Then
eButton.Click
Exit For
End If
Next
End Sub
Any advise on what I'm doing wrong would be great!
You can get rid of your For...Next loop at the bottom and replace it with this to click the button:
doc.forms(0).submit
The 0 can be changed to another number (such as 1 or 2) to click on a different button. If there are multiple buttons on a page that can be clicked on it will just take some trial and error to find out which number matches the button you want to click.
Strangely enough I didn't find any information on the topic and I'm currently stuck at the point where I managed to open a new tab in an instance of IE by programmatically clicking a button, but I haven't the faintest clue of how to address the new tab in order to get information from there (the button basically brings up a new tab with the result of a search).
This is basically a straightforward question, but I'm including my code anyway:
Sub AddInfoFromIntranet()
Dim Ie As SHDocVw.InternetExplorer
Dim URL As String
Dim iFrames As MSHTML.IHTMLElementCollection
Dim iFrame As MSHTML.HTMLFrameElement
Dim Doc As MSHTML.HTMLDocument
Dim InputBox As MSHTML.IHTMLElementCollection, htmlButton, allTags, Tag
' Opens Intranet - yeah, sadly it's not a public web page
URL = "{My intranet website}"
Set Ie = New SHDocVw.InternetExplorer
With Ie
.navigate URL
.Visible = True
While .Busy Or .readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set Doc = .document
End With
' Gets top_window frame and navigates to it, then inserts the name to search
Set iFrames = Doc.getElementsByName("top_window")
If Not iFrames Is Nothing Then
Set iFrame = iFrames(0)
Ie.navigate URL & iFrame.src
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set InputBox = Doc.getElementsByName("Nachnamevalue")
If Not InputBox Is Nothing Then InputBox(0).Value = "test"
' Clicks on "search"
Set allTags = Doc.getElementsByTagName("input")
For Each Tag In allTags
If Tag.Value = "suchen" Then
Tag.Click
Exit For
End If
Next
' Here a new tab is opened, must find info in this tab
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
' HERE I HAVE NO CLUE WHAT TO WRITE. THE CODE ABOVE WORKS FLAWLESSLY
End If
Set Doc = Nothing
Set iFrames = Nothing
Set iFrame = Nothing
Set InputBox = Nothing
Set allTags = Nothing
Set Ie = Nothing
Ie.Quit
End Sub
Now, is there a way to address a tab by: 1) its name (and where do I find it) 2) its position in browser 3) the status (if it is "active") ?
Bonus questions: since I am new to VBA and Internet Explorer interaction, what exactly are the variables: htmlButton, allTags, Tag ? Also, could anyone explain if I need to set all the variables at the end to nothing, or I just need to set the Internet Explorer to nothing?
Thanks in advance!
See below for a function you can use to get an open IE document window - I don't think IE exposes any simple (VBA-accessible) API for working directly with tabs or determining whether a specific tab is active.
allTags is a collection of DOM elements with type "" , and Tag is a single memeber of that collection.
You do not have to set objects to Nothing before exiting a Sub (though some people still do that) - the VBA runtime will take care of that for you.
Sub TestGetIE()
Dim IE As Object
Set IE = GetIE("http://stackoverflow.com")
If Not IE Is Nothing Then
IE.document.execCommand "Print", False, 0
End If
End Sub
'Get a reference to an open IE window based on its URL
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
sURL = ""
On Error Resume Next
'check the URL and if it's the one you want then
' assign it to the return value
sURL = o.document.Location
On Error GoTo 0
'Debug.Print sURL
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function