I need to enter a site for which a proxy form has to be filled. I couldn't get through the form using Selenium VBA.
I called a VBS script from VBA to fill the form. It works when the PC is not locked.
Below is the proxy form.
Outlook VBA code to call VBS:
Dim bot as new chromedriver
bot.Start "chrome", "https://nissan.service-now.com/nav_to.do?uri=%2Fhome.do%3F"
bot.Get ("https://nissan.service-now.com/nav_to.do?uri=%2Fhome.do%3F") '//load webpage
strFileName = "d:\LocalData\Z018439\Desktop\MY\NX-AMO\VBACodes\Shell.vbs"
Set oshell = CreateObject("Wscript.shell")
oshell.Run "vbsc " & strFileName '//call vbs file
VBS code to fill proxy form:
Sub test()
Dim shell_object
Dim app_path, time
wscript.Sleep 12000
shell_object = "wscript.shell"
Set objshell = CreateObject(shell_object)
objshell.SendKeys ""
objshell.SendKeys "{Tab}"
objshell.SendKeys ""
objshell.SendKeys "{Enter}"
End Sub
When the PC is locked, keyboard function is disabled and hence sendkeys(VBS) is not working. Launch is done upon arrival of a new mail in Outlook.
How do I fill the proxy form when the PC is locked.
Related
Windows 10
Microsoft 365
Outlook v.2205
I am writing a macro that prints the selected email AND attachments to PDF. I need this to be fully automatic, without any user intervention once the macro starts. The problem I have, is that when the mailItem.PrintOut command is used, a print dialogue window appears and freezes the macro until the user advances the window manually.
I am able to cobble together the body of the email using the Word object library where I can easily print, but for email attachments (such as PDFs) I am at a loss.
I have scoured the web looking for a solution to this. I have found nothing so far that can be done in pure native VBA.
Image of the printer dialogue that I would like to bypass:
I previously asked here whether it is possible to manipulate the printer dialogue window using API/VBA code, but later realized that once the printer dialogue appears, VBA stops working so I must find a way to bypass the dialogue window altogether.
It seems unlikely to me that there does not exist a way to do this.
Code posted below (simplified for reference):
Private Sub printEmail()
Dim mySelection As Outlook.Selection
Dim myEmail As MailItem
Set mySelection = Application.ActiveExplorer.Selection
' If item = mailitem, print
If mySelection.Item(1).Class = 43 Then
Set myEmail = mySelection.Item(1)
myEmail.PrintOut ' <===###this command causes a dialogue to appear###
' Else, exit sub
Else
MsgBox "Select a mail item"
Exit Sub
End If
End Sub
You need to save attached files (for example, PDF) on the disk and then use a shell command to print the saved file. Or if you have got Acrobat Reader installed on the system you could use something like that:
Dim oShell As Object, oExec As Object
Set oShell = CreateObject("Wscript.Shell")
Set oExec = oShell.exec("""" & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" _
& """/p /h """ & SomePath & "\" & "invoice.pdf" & """")
DoEvents
oExec.Terminate
Set oExec = Nothing
Set oShell = Nothing
I inherited this VBA script from my predecessor. It works fine for me in Excel 2013 up until recently when I was told I may need to work from home. Come to find out, the Office 2016 environment of my newly accessed VPN desktop does not like this script. I keep getting "The remote server machine is unknown or unavailable" when it reaches .ReadyState <> READYSTATE_COMPLETE.
The navigation did not fail as I can see the window where it successfully navigated to the URL and I can interact with it correctly. The strange thing is if I change the URL to "www.google.com" I get a valid ready state result.
I also need to figure out how to late bind the Shell Windows so it will work with both the v15 and v16 libraries simultaneously.
The intent of this script is to automate a process that
1. Opens an internal database at DBurl via web interface
2. Manipulates and runs a java script located on the web page
3. Close the browser window without closing any other browser windows
This could be modified for someone else's use by looking for a page element, such as a search box or specific button on a page, and interacting with it.
Edit:
Additional testing has revealed that a pause at and skipping the Do While loop and resuming at IETab1 = SWs.Count results in this script working in Office 2016. The only issue, then, is without the loop, the page isn't yet ready for the next step when the script tries to run the interaction. A wait for 5 seconds in place of the loop band-aid's this issue. Finding why the .ReadyState won't read will fix this issue.
Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" _
(ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Sub OpenWebDB()
Dim ieApp As Object
Dim SWs As ShellWindows
Dim IETab1 As Integer
Dim JScript As String
Dim CurrentWindow As Object
Dim DBurl As String
Dim tNow As Date, tOut As Date
DBurl = "My.Database.url"
Set SWs = New ShellWindows
tNow = Now
tOut = tNow + TimeValue("00:00:15")
If ieApp Is Nothing Then
Set ieApp = CreateObject("InternetExplorer.Application")
With ieApp
.Navigate DBurl
Do While tNow < tOut And .ReadyState <> READYSTATE_COMPLETE
DoEvents
tNow = Now
Loop
IETab1 = SWs.Count
End With
End If
If Not tNow < tOut Then GoTo DBFail
On Error GoTo DBFail
Set CurrentWindow = SWs.Item(IETab1 - 1).Document.parentWindow
JScript = "javascript: DoSomething"
Call CurrentWindow.execScript(JScript)
On Error GoTo 0
SWs.Item(IETab1 - 1).Quit
Set ieApp = Nothing
Set SWs = Nothing
Exit Sub
DBFail:
MsgBox (DBurl & vbCrLf & "took too long to connect or failed to load correctly." & vbCrLf & _
"Please notify the Database manager if this issue continues."), vbCritical, "DB Error"
SWs.Item(IETab1 - 1).Quit
Set ieApp = Nothing
Set SWs = Nothing
End Sub
Try to remove the tNow < tOut from the Do While condition. Or, using the While statement to wait page complete:
While IE.ReadyState <> 4
DoEvents
Wend
The intent of this script is to automate a process that
1. Opens an internal database at DBurl via web interface
2. Manipulates and runs a java script located on the web page
3. Close the browser window without closing any other browser windows
Besides, according to the intent of the script, I suggest you could refer the following code (it could loop through the tabs, and close specific tab according the title):
Sub TestClose()
Dim IE As Object, Data As Object
Dim ticket As String
Dim my_url As String, my_title As String
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "https://www.microsoft.com/en-sg/" '1st tab
.Navigate "https://www.bing.com", CLng(2048) '2nd
.Navigate "https://www.google.com", CLng(2048) '3rd
While IE.ReadyState <> 4
DoEvents
Wend
'wait some time to let page load
Application.Wait (Now + TimeValue("0:00:05"))
'get the opened windows
Set objShell = CreateObject("Shell.Application")
IE_count = objShell.Windows.Count
'loop through the window and find the tab
For x = 0 To (IE_count - 1)
On Error Resume Next
'get the location and title
my_url = objShell.Windows(x).Document.Location
my_title = objShell.Windows(x).Document.Title
'debug to check the value
Debug.Print x
Debug.Print my_title
'find the special tab based on the title.
If my_title Like "Bing" & "*" Then
Set IE = objShell.Windows(x)
IE.Quit 'call the Quit method to close the tab.
Exit For 'exit the for loop
Else
End If
Next
End With
Set IE = Nothing
End Sub
I'm not able to have interaction with Windows PopUp to write a dedicated path to upload a file in VBA using Selenium due to Chrome browser.
I have found some solutions in Python but nothing in VBA. This is why I have tried to convert the code in VBA but without success.
Find below an example code:
Sub Fullfil_Windows_PopUp()
Dim driver
Dim elem
Set Waiter = CreateObject("Selenium.Waiter")
Set Assert = CreateObject("Selenium.Assert")
Set driver = CreateObject("Selenium.ChromeDriver")
'open the browser and the page
driver.Get "https://fr.imgbb.com/"
While Waiter.Not(InStr(driver.Title, "ImgBB — Upload Image — Hébergement d'images gratuit")): Wend
'open upload window
Set elem = driver.FindElementsByXPath("//*[#id='home-cover-content']/div[2]/a").Item(1)
elem.Click
'Trial 1
driver.SwitchToWindowByTitle "Ouvrir" '--> NOK (error window not found)
driver.SendKeys "D:\Test.jpg"
'Trial 2
driver.SwitchToAlert.SendKeys "D:\Test.jpg" '--> NOK (error No Alert present)
'Trial 3
Set wsh = CreateObject("WScript.Shell")
wsh.SendKeys "D:\Test.jpg" '--> NOK (no action)
End Sub
Thanks in advance for your suggestions
I have used a "back door" to fill the file name into the filemanager window.
As the cursor is already into the filename field of the window, I have created an external script in VBS to write the file name (and 2x TAB + ENTER to validate the window).
Below the code of the VBS file:
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.SendKeys "D:\Test.jpg"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{ENTER}"
And I execute this script after to have open the filemanager window with selenium:
Sub Fullfil_Windows_PopUp()
Dim driver
Dim elem
' Chrome browser
Set driver = CreateObject("Selenium.ChromeDriver")
'open the browser and the page
driver.Get "https://fr.imgbb.com/"
Sleep 1000
' Open upload window
Set elem = driver.FindElementsByXPath("//*[#id='home-cover-content']/div[2]/a").Item(1)
elem.Click
' Write the filename with VBS script
Set oWsh = CreateObject("Shell.Application")
oWsh.ShellExecute "D:\filename.vbs"
Set oWsh = Nothing
Sleep 1500
End Sub
But I continue to search a solution directly with Selenium because for example, the filename is directly indicated into the VBS File and this is not easy to use it like a variant.
#Armin's answer works quite well if you are in a similar quandary. I don't know of any other method at present to interact with a file window at upload point.
For more details, a VBS file is a Microsoft VB-Script file. You can create this using Notepad, putting in the code, save as, change file name, include ".vbs" extension and change file type to all files.
If you use the code in the answer as it is, you're likely to be greeted with an unfriendly "Undefined Variable" error so you should declare the variable first as an object:
Dim oWsh as Object
Depending on your code, you may also be greeted with an error for the "Sleep*" command used. You can change this to using an implicit or explicit "Wait" as needed:
driver.Wait 1500
Cheers!
I am limited to using VBA to accomplish this. The goal is to programmatically Open a new IE window which is a duplicate of a window already open.
I need to display this window for limited amount of time (in this example I am waiting 15 seconds), then I want to close one of the two IE windows I have open.
I have cobbled together code fragments from a few examples I have found and this is partially working, but the results are not as I would expect.
First I am able to find the IE instances but even though I think I have coded an exit, both windows are closed.
The MsgBox I am using for debugging never appears.
With each run of the code the error message below appears
Below is the code I am trying to get to work, but failing with.
Private Sub OpenReport()
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://~~~~~~~~~.net/reports/views/result/reportResult.faces"
' Wait for a period of time contained in TimeValue
Application.Wait (Now + TimeValue("00:00:15"))
' Now close ONE of the IE windows (Currently closing all of them)
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
' Find IE Instances
For Each objItem In colItems
If objItem.Name = "iexplore.exe" Then
On Error Resume Next
objItem.Terminate ' Terminates all instead of exiting after finding one IE window
MsgBox objItem.Name & " " & objItem.ProcessID & " " & objItem.CommandLine 'Doesn't appear
Exit For
End If
Next
End Sub
I appreciate the input but had to go a slightly different route to get this working as it should...
The key to getting one instance of IE to close was solved by using TaskKill (commandline WScript).
Below is the full solution
Private Sub OpenReport()
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://~~~~~~~~~~~net/reports/views/result/reportResult.faces"
' Wait for a period of time contained in TimeValue
Application.Wait (Now + TimeValue("00:00:15"))
' Now close ONE of the IE windows (Currently closing all of them)
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
' Find an IE instance
For Each objitem In colItems
If objitem.Name = "iexplore.exe" Then
On Error Resume Next
Shell ("TaskKill /PID " & objitem.ProcessID)
Exit For
End If
Next
End Sub
I want to read web pages using Excel VBA. How do I carry out this task? Is it even possible?
Coming from Excel 2003, yes this is possible - you may use the SHDocVw.InternetExplorer and MSHTML.HTMLDocument objects to call a web page, gain control over and interact with the DOM object. After creating references to Microsoft HTML Object Library (...\system32\MSHTML.TLB) and Microsoft Internet Control (...\system32\ieframe.dll) you can play with the following example:
Sub Test()
Dim Browser As SHDocVw.InternetExplorer
Dim HTMLDoc As MSHTML.HTMLDocument
Set Browser = New SHDocVw.InternetExplorer ' create a browser
Browser.Visible = True ' make it visible
Application.StatusBar = ".... opening page"
Browser.navigate "http://www.google.com" ' navigate to page
WaitForBrowser Browser, 10 ' wait for completion or timeout
Application.StatusBar = "gaining control over DOM object"
Set HTMLDoc = Browser.document ' load the DOM object
WaitForBrowser Browser, 10
' at this point you can start working with the DOM object. Usefull functions are
' With HTMLDoc
' .getElementByID(string)
' .getElementsByTagName(string)
' .getElementsByName(string)
' .getAttribute(string)
' .setAttribute string, string .... to change field values, click a button etc.
' End With
Application.StatusBar = "" ' time to clean up
Browser.Quit
Set HTMLDoc = Nothing
Set Browser = Nothing
End Sub
Sub WaitForBrowser(Browser As SHDocVw.InternetExplorer, Optional TimeOut As Single = 10)
Dim MyTime As Single
MyTime = Timer
Do While Browser.Busy Or (Timer <= MyTime + TimeOut)
DoEvents
Loop
' if browser still busy after timeout, give up
If Browser.Busy Then
MsgBox "I waited for " & Timer - MyTime & " seconds, but browser still busy" & vbCrLf & _
"I give up now!"
End
End If
End Sub
You can use VBA to automate IE (plenty of examples via Google) or you can fetch the page directly using an instance of MSHTTP (ditto plenty of examples on the web). Which is best for your needs will depend on exactly what you want to do. Hard to say more without more detailed requirements.