I have a macro on VBA in the process of which several Chrome windows open.
In each of the windows I need to do different actions and for this I need to switch between them.
Can I somehow get a list of the names of the open Chrome windows or their handles in the VBA?
Such methods did not work in VBA:
driver.getWindowHandles
driver.getWindowNames
In JS, you can get the window name:
window_name = driver.ExecuteScript("return window.name;")
Perhaps there is a way to get the names of all the windows and cycle through them in the VBA?
I found a way to more or less resolve this issue.
We save the name of each window to be opened in a variable
window_count = driver.Windows.Count 'count all chrome windows
i = 0
For i = 1 To window_count
If driver.Windows.item(i).Title <> "SomeTitle 1" And driver.Windows.item(i).Title <> "SomeTitle 2" Then
window_name = driver.Windows.item(i).Title 'at this moment the desired window is
'activated and you can work in it even
'without driver.SwitchToWindowByTitle
MsgBox driver.URL
End If
Next i
I think this is not the best solution to the problem, but with my knowledge it’s better to do so far I can’t
Related
I'm using MSAccess VBA with Selenium VBA, Chromedriver
I am able to get to a website, login, find the button to click to start download, and get that download to save to the location I want.
I want to track the progress.
I have opened a new Chrome window (tab) and navigated to chrome:\\downloads\ and switched my driver window to that window.
I've used the following code I found on stack overflow, in a loop to monitor the progress.
downloadPercentage = wd.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")
It returns this error ...cannot return properties of null...
My download is present on the page. I can get the file name.
When I open the developer tab on the downloads page and enter the same query selector path into the console I get the same thing. It returns null.
If I manually (or maybe even using VBA haven't tried) click the button for a second download, then all of a sudden that same code returns a value of 100. (It may catch it at a lower percent. The download is too fast for me to catch that in debug mode.)
What would cause the selector to not be present for one download, but then present for the next?
Here's the code that's in question.
Function getDownloadedFileName(wd as ChromeDriver) As String
Dim startTime As Date
'I'm using this method because opening a second ChromeDriver instance and going to the chrome://downloads/ page returns a clean slate (no downloads) and this method works for me.
wd.ExecuteScript ("window.open()")
wd.SwitchToNextWindow
wd.Get "chrome://downloads/"
startTime = Now()
Dim downloadPercentage As Integer
Do While DateDiff("s", startTime, Now()) < 120 And downloadPercentage < 100
'This is the line that returns the Javascript error ... Cannot read properties of null ...
downloadPercentage = wd.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")
If (downloadPercentage = 100) Then
getDownLoadedFileName = wd.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').text")
Exit Do
End If
Loop
wd.SwitchToPreviousWindow
End Function
I'll appreciate any help on this. Thanks!
I'm working on a VBA program to help automate a task using UI Automation, but I've run into an issue where the window of the program I'm trying to control does not show up as a child of the Root Element (desktop).
It's my understanding that all elements are children/descendants of the desktop element, so why it's not showing up is puzzling. Here is the code I'm using to see all the children of the Desktop element:
Sub test_get_windows()
Dim oAutomation As New CUIAutomation
Dim oDesktop As UIAutomationClient.IUIAutomationElement
Dim oCondition As UIAutomationClient.IUIAutomationCondition
Dim oChilds As UIAutomationClient.IUIAutomationElementArray
Dim i As Integer
Set oDesktop = oAutomation.GetRootElement
Set oCondition = oAutomation.CreateTrueCondition
Set oChilds = oDesktop.FindAll(TreeScope_Children, oCondition)
For i = 0 To oChilds.Length - 1
Debug.Print oChilds.GetElement(i).CurrentName
Next i
End Sub
I see everything except the window I'm trying to interact with. I tried the code on another computer, and I'm able to see the window.
Computer where it doesn't work:
Computer where it does work:
The AcSELerator Quickset window does not show up on the first computer but it does on the second, so I don't think it's a problem with the application. Both computers have the same version installed and are running Windows 10 Enterprise. Any ideas on what the issue could be or any troubleshooting steps I can try?
The window doesn't have to be minimized. Try veryfyng that. That's what was happening to me. Similar case and Similar routine.
I built a very complex SeleniumBasic via VBA via Excel Addin setup that interacts with one of the leading ticketing system websites to scrap and populate data. The system interacts with 90+ different fields/clickables with 3 different pages, 6 different tabs, and nested popups...deployed to 120 users who use the automations about 20 times per day.
And it has been working flawlessly for over a year...
We have just provisioned 20 more users on the same system, and their automations refuse to work.
Here is where I am at with my research:
I am able to manually step through code on the new system and have it successfully go through the entire automation, so the issue probably has something to do with the speed VBA/Selenium is trying to interact with the website.
Once the system is unable to find a field or clickable, it refuses to find any other ones after that.
The way the system is built in order to go as fast as possible is via standard VBA error handling. It fails to find something, it goes to the error handler, the error handler says to wait for one second then try again. Again, this system has been working flawlessly for over a year and is currently working on 120 user's systems.
To see if maybe Selenium was refusing to reload the clickable, I broke out the error handling from a Resume to a Resume Next, and then had a do while loop with a boolean flag to keep trying until it was successful, but after the first failure, it refused to find anything else, including different fields
The one thing the 20 new users have in common is that they are all using v66 of Chrome, whereas all of the systems that are working have old copies of Chrome that are at least 9 months old
Thinking this might be an issue, I grabbed all of the ChromeDrivers and systematically went through one by one to test if we got a different performance with a different ChromeDriver, but all of the ChromeDrivers had the same error
So that is where I stand. I'm wondering if there is some key insight I am missing or a workaround that will get newer versions of Chrome to retry the fields. Or...do I need to try a VBA/Selenium tool other than SeleniumBasic to fix this. Or...do I need to roll back these 20 users to older versions of Chrome.
Thanks for sharing your expertise.
''''Check to see if there are any aliases=================================
For AliasCheck = 2 To AliasCounter + 1
If Hash = Sheets("Temp Subjects & Locations").Range("AY" & AliasCheck) Then
AliasName = Sheets("Temp Subjects & Locations").Range("AY" & AliasCheck)
AliasCount = AliasCount + 1
AliasDisplayName = Sheets("Temp Subjects & Locations").Range("AZ" & AliasCheck)
temp1 = ""
temp2 = ""
Call countryDictionary
'drops the country back into Excel to later remove the dupes
temp1 = Sheets("Temp Subjects & Locations").Range("BA" & AliasCheck)
temp2 = dict(temp1)
Sheets("Temp Subjects & Locations").Range("BG" & AliasCount + 1) = temp2
''''Click to add AKA's names
iframeText = "iframe_win_" & AddParty
robot.SwitchToDefaultContent
robot.SwitchToFrame iframeText
iframeTracker = iframeTracker + 1
iframeText = "iframe_win_" & iframeTracker
robot.SwitchToDefaultContent
robot.SwitchToFrame iframeText
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
robot.FindElementById("dijit_form_Button_0").Click
End If
Next AliasCheck
The AddParty variable is a way to track the number of the pop-up we came from.
The iFrameTracker variable is a way to track the number of the pop-up we are going to...the system sequentially numbers its pop-ups...instead of legible names...
The newer systems will make it down to the SendKeys and then decide not to work. On a resume next, it will then refuse to find the OK button ("dijit_form_Button_0")
Here is the code I was playing around with to see if I could get it to retry using a "Resume Next" instead of a "Resume"
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
Do While FailRetry = True
FailRetry = False
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
Loop
errHandler4:
If errorCounter < 21 Then
Application.wait (Now + TimeValue("00:00:01"))
errorCounter = errorCounter + 1
FailRetry = True
Resume Next
Else
MsgBox "Reached 20 second timeout. Stopping processing."
Exit Sub
End If
I have a simple VBA code (see below), that goes to a webpage, selects some value, clicks the “Begin download” button, and then saves the file. The problem is I am stuck at the “clicking the download button” part. Can someone help?
Here is the code:
Sub Treasury_Auc_Notes()
Dim IE As Object
Set IE = Nothing
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://www.treasurydirect.gov/RI/OFAuctions?form=ndnld&typesec=notes"
While IE.Busy
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
'Click "Begin download" button (this is where I am stuck)
'Choose Save Open or Cancel (I haven’t got to this part yet)
ActiveWorkbook.SaveAs Filename
End Sub
This one's tricky, and due to restrictive security on my laptop, I'm not able to verify this 100%, but try:
While IE.ReadyState <> 4
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
Dim ele As Object
For Each ele In IE.Document.Forms
If ele.Action = "/RI/OFAuctions" Then
ele.Submit
Exit For
End If
Next
You may have to use SendKeys (I think Application.SendKeys "o") method to open the file then use VBA to save the ActiveWorkbook to the desired location. I'm not able to test SendKeys for reasons mentioned below.
Or, I'm pretty sure there is a WinAPI functions that can do this more reliably than SendKeys. You'll need to get the hWnd of the Save dialog and do some other stuff to force it to open/save. This is fairly advanced VBA that I probably have a reference to somewhere, but rarely need to use it. If you have trouble with this particular part, I would urge you to ask a separate question "How to get the hWnd of File Save dialog and download file from IE" or something like that.
NOTE: I can't test the SendKeys method. When I use the above code, I am fairly certain the file is being downloaded, but it is going to a temporary folder that is hidden, and difficult to find. In any case, it does appear to be downloading with some manual intervention. I get this warning:
I click to ignore that (I have no idea how to automate this part, I'm just trying to validate that the form .Submit method actually worked), and after some creative searching (temporary internet files get dumped in a strange/hidden folder usually) I verify the file is downloaded, although it is showing as a TXT extension instead of CSV.
If instead of using VBA, I click on the button manually, and I choose to "open" the file opens as CSV and has the same path to that temporary internet location.
I have a Word template (suggestion from) which includes an autonew macro to insert a reference number at a book mark and an action button (Submit)which saves the resulting document with the reference number as part of the file name and closes Word. This works perfectly well when opening the template via Windows Explorer.
We also have a PowerPoint show with action settings hyperlinking to various documents. The link will open the above template OK but does not insert the reference number. Also when the 'submit' button is hit, the file saves as another template with the reference number included.
I am not sure if the issue is Word or PowerPoint-related. The code for the Word template is
Sub AutoNew()
REF = System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", _
"MacroSettings", "REF")
If REF = "" Then
REF = 1
Else
REF = REF + 1
End If
System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", "MacroSettings", _
"REF") = REF
ActiveDocument.Bookmarks("REF").Range.InsertBefore Format(REF, "000#")
End Sub
Private Sub CommandButton1_Click()
REF = System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", _
"MacroSettings", "REF")
ActiveDocument.SaveAs FileName:="L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Suggestion " & Format(REF, "000#.doc")
Application.Quit
End Sub
Any help or pointers would be appreciated as if it works I'd like to use for various other templates.
From the description, it's kind of hard to get an accurate idea of what's happening, but it SOUNDS like the the AUTONEW just might not get run in that particular combination.
You could verify this by using some logging or MSGBOX calls to see exactly what macros are being run, when.
Check the docs on Autonew here
http://support.microsoft.com/kb/211659
Sounds like it won't run if the macro is saved in Normal, which doesn't sound like the case here but it's worth noting.
You might also consider using the AutoOpen macro and checking other elements to make sure this is a brand new doc instead of one that's already been saved (like checking the content of the Document.Fullname property).