I am writing a macro to download a csv file from my company's internal website.
For many reasons I can't use any xmlhttp objects. The macro will download the file. The problem is Internet Explorer 9 prompts the user with Open, Save, and Cancel buttons.
While in IE, Alt+Shift+S will save the download, but I can't get the Sendkeys "%+s" method from Excel VBA to work.
Here is the relevant code:
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 "%+s", True
followLinkByText = True
Exit Function
End If
Next
End Function
Like I mentioned in my comments, The Info Security bar makes it difficult to interact with the File Download Window.
An alternative is to use the webbrowser control and then passing the URL to it. But the main problem with this method is that you cannot have the webbrowser in the same Excel Instance. Once the File Download window pops up your entire VBA Macro will come to a standstill till the time you do not dispose it off.
Here is an alternative. Here is a small exe that I created in VB6 which will pop up the File Download window bypassing the IE Info Security Bar. And once the File Download window pops up, you can interact with it using the APIs as shown in my blog article.
Let's take an example to see on how we interact with this vb6 exe file.
Create a module in Excel and paste this code.
IMPORTANT NOTE: Since you didn't give me any URL, I am taking a Static URL. Please replace it with your link. Now depending upon the link that you specify, you might see the one of these two download windows. Based on the download window that you see you will have to find the window handles based on the pic shown below. More details on the blog link that I gave.
Download the file attached and save it in say C:\. If you save it in any other location then amend that in the Shell statement below.
Sub Sample()
Dim sUrl As String
sUrl = "http://spreadsheetpage.com/downloads/xl/king-james-bible.xlsm"
Shell "C:\FDL.exe " & sUrl, vbNormalFocus
End Sub
SNAPSHOT
FILE: The file can be downloaded here.
You may try this as it is worked for me on IE 11:
Copy file C:\Windows\System32\UIAutomationCore.dll file to users Documents i.e C:\Users\admin\Documents then add reference UIAutomationClient to your macro file.
Paste below code in your module:
Option Explicit
Dim ie As InternetExplorer
Dim h As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Sub Download()
Dim o As IUIAutomation
Dim e As IUIAutomationElement
Set o = New CUIAutomation
h = ie.Hwnd
h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString)
If h = 0 Then Exit Sub
Set e = o.ElementFromHandle(ByVal h)
Dim iCnd As IUIAutomationCondition
Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "Save")
Dim Button As IUIAutomationElement
Set Button = e.FindFirst(TreeScope_Subtree, iCnd)
Dim InvokePattern As IUIAutomationInvokePattern
Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern.Invoke
End Sub
Try at your end.
I think I came up with a simpler solution: when the download bar appears in IE9, just by-pass it by displaying the "real" Download Pop Up window. The shortcut is "CTRL+J". All you have to do next is click on "Save" or "Open". There might be pretty ways to do it, but I simply send a key sequence to move the focus on desired option and then press enter.
Here is the code:
' Wait for download bar to appear
Application.Wait (Now + TimeValue("0:00:04"))
' Sending CTRL+J to open download pop-up
SendKeys "^j"
' Wait for download popup to appear
Application.Wait (Now + TimeValue("0:00:02"))
' Sending keys sequence to click on "Save" button
SendKeys "{RIGHT}{RIGHT}{RIGHT}~"
Your Application.Sendkeys just needs a tweak. Below is the code I am using so it is tested on IE11. This is for Alt+S with no Shift which is the keyboard shortcut in IE11. Let me know if this doesn't work and you need help adding the Shift back in.
Application.SendKeys "%{S}", True
Related
Suppose I have two hyperlinks (on excel sheet) referring to two documents:
e.g ( A.doc and B.doc ) on my local intranet.
I will open the first document "A.doc" then I will open the second one "B.doc"
The problem:
If there is already an opened word document and then I clicked hyperlink (Word Document on my local intranet),
The later file is not opened automatically and I have to click on the flashing taskbar button to open the cited second file.
This issue occurs only with Microsoft word documents found on my local intranet.
If there is no open document and I clicked on any word hyperlink, It opens normally without any issue.
Please watch this short video to understand my problem.
I need to utilize FollowHyperlink event in excel or any other method to:
bring the previous opened window A.doc to front and then bring the second one B.doc to front.
you may find it a strange question! But I have to do it manually each time to show and bring the second one to front.
I have used this API code (in a Word document) on Normal-ThisDocument:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Dim LHwnd As Long
Private Sub Document_Open()
If Application.Documents.Count > 1 Then
LHwnd = FindWindow("rctrl_renwnd32", Application.ActiveWindow.Caption)
SetForegroundWindow (LHwnd)
End If
End Sub
And used that code on my excel sheet itself:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
On Error Resume Next
Dim objWd As Object
Set objWd = GetObject(, "Word.Application")
AppActivate objWd.ActiveWindow.Caption
Set objWd = Nothing
End Sub
Finally, I found this helpful page Bring an external application window to the foreground But I could not adapted it to my need.
Please, try the next BeforeDoubleClick event. If the problem is related only to hyperlinks, it should work...
Option Explicit
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.column = 1 And Target.Value <> "" Then 'limit this behavior to the first column
If LCase(left(Target.Value, 5)) = "http:" Then
Cancel = True
Dim objWd As Object, d As Object, arrD: arrD = Split(Target.Value, ".")
If LCase(left(arrD(UBound(arrD)), 3)) <> "doc" Then Exit Sub
On Error Resume Next
Set objWd = GetObject(, "Word.Application") 'find the Word open session, if any
On Error GoTo 0
If objWd Is Nothing Then
Set objWd = CreateObject("Word.Application")
End If
With objWd
.Visible = True
Set d = .Documents.Open(Target.Value)
End With
'force somehow the new open document window expose its handler...
Dim i As Long
Do Until objWd.ActiveWindow.Caption = d.name Or _
objWd.ActiveWindow.Caption = left(d.name, InstRev(d.name, ".")-1) & " [Read-Only] [Compatibility Mode]"
i = i + 1: Debug.Print objWd.ActiveWindow.Caption, left(d.name, InstRev(d.name, ".")-1) & " [Read-Only] [Compatibility Mode]"
DoEvents: If i >= 10 Then Exit Do 'just in case, if something unexpected happens...
Loop
SetForegroundWindow CLngPtr(objWd.ActiveWindow.hWnd)
End If
End If
End Sub
It should work in 64 bit, but it is easy to be adapted for both cases, supposing that it works as you need.
I am very new to Stack Overflow & VBA so please pardon me for any mistakes in my question.
We are trying to download a table into a .txt file from the SAP GUI interface using scripting
Whenever we try to run the code we get the error "the control could not be found by id".
The button which we are trying to press
Things we tried:
We tried using Send keys but we are not very confident on it. It will be our last resort.
When we used FindAllByName with "shell" it clicks the "Export" button on the table below it
From what I can understand
The numbers (Italized or marked with ** in code) in the script keep changing. So we guess there is a clash between the stored script number in SAP and in the excel from which we are trying to run
The Table which we are trying to interact only appears when we load sum part numbers and hit "Go". It wont appear when we initially open the GUI.
Public Declare Function SetForegroundWindow _
Lib "user32" (ByVal hwnd As Long) As Long
Sub SA_Dump()
Dim App, Connection, session As Object
Set SapGuiAuto = GetObject("SAPGUI")
Dim setFocus As Long
Set App = SapGuiAuto.GetScriptingEngine
Set Connection = App.Children(0)
Set session = Connection.Children(0)
Dim wsh As Object
Set wsh = CreateObject("WScript.Shell")
Dim sCestaGrid As String
Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row).Copy
setFocus = session.ActiveWindow.Handle
SetForegroundWindow setFocus
Application.Wait (Now + TimeValue("0:00:05"))
'Reset fields
session.findById("wnd[0]").resizeWorkingPane 147, 25, False
session.findById("wnd[0]/usr/subSUB01:/SCF/SG/CA_110SPPDRPSB1:1005/subSUB01:/SCF/SG/CA_110SPPDRPSB1:1001/btnRESETSIMPLESEL").press
'hit selection window
session.findById("wnd[0]/usr/subSUB01:/SCF/SG/CA_110SPPDRPSB1:1005/subSUB02:/SCF/SG/CA_110SPPDRPSB1:1002/btnSGNT_0000034-MATNR_V").press
'hit copy from clipboard
session.findById("wnd[1]/tbar[0]/btn[24]").press
'hit Check entries mark
session.findById("wnd[1]/tbar[0]/btn[0]").press
'hit Copy button
session.findById("wnd[1]/tbar[0]/btn[8]").press
'hit Go button
session.findById("wnd[0]/usr/subSUB01:/SCF/SG/CA_110SPPDRPSB1:1005/subSUB01:/SCF/SG/CA_110SPPDRPSB1:1001/btnBUTTON01").press
'Clear clipboard to avoid pop-up at end to close Excel sheets
Application.CutCopyMode = False
'hit export (ERROR HAPPENS HERE!!!)
session.findById("wnd[0]/usr/subSUB02:/SCF/SG/CA_110SPPDRPSB1:*2119*/subSUB03:/SCF/SG/CA_110SPPDRPSB1:*2141*/cntlCONTAINER_7/shellcont/shell").pressToolbarContextButton "&MB_EXPORT"
session.findById("wnd[0]/usr/subSUB02:/SCF/SG/CA_110SPPDRPSB1:*2119*/subSUB03:/SCF/SG/CA_110SPPDRPSB1:*2141*/cntlCONTAINER_7/shellcont/shell").selectContextMenuItem "&PC"
'hit Tick button
session.findById("wnd[1]/tbar[0]/btn[0]").press
'For rename
session.findById("wnd[1]/usr/ctxtDY_FILENAME").Text = "Rel_mvmnt.txt"
session.findById("wnd[1]/usr/ctxtDY_FILENAME").caretPosition = 10
'Hit replace button
session.findById("wnd[1]/tbar[0]/btn[11]").press
End Sub
I use this way and it works:
session.findById("wnd[0]/tbar[0]/okcd").text = "%pc"
Let me know if it worked for you.
I want to embed an explorer-window into my excel worksheet, to display some folder contents that are related to my workbook.
I use the following code, which works quiet well:
Sub AddOleBrowser()
Dim OleBrowser As OleObject
Dim Browser As Object
Set OleBrowser = ActiveSheet.OLEObjects.Add(ClassType:="Shell.Explorer.1", Link:=False, DisplayAsIcon:=False)
Set Browser = OleBrowser.Object
Browser.Navigate "X:\" 'Actually some network-path related to my workbook-path
OleBrowser.Activate
End Sub
My problem is, that the OleBrowser keeps getting replaced by a low-res image, displaying the contents of the folder instead, whenever I click somewhere into my worksheet. When I double-click it, it returns to the normal browser view until it loses focus again. I want to add multiple browser windows to my worksheet, so they all should stay "activated".
I also tried to add a frame instead, which then holds a browserobject:
Sub AddOleFrameWithBrowser()
Dim OleFrame As OleObject
Dim CtrlBrowser As Control
Dim Browser As Object
Set OleFrame = ActiveSheet.OLEObjects.Add("Forms.Frame.1", Link:=False, DisplayAsIcon:=False)
Set CtrlBrowser = OleFrame.Object.Controls.Add("Shell.Explorer.2", "Browser") 'Frame1 is an MSForms.Frame-object that I placed there before.
CtrlBrowser.Left = 0
CtrlBrowser.Top = 0
CtrlBrowser.Width = OleFrame.InsideWidth
CtrlBrowser.Height = OleFrame.InsideHeight
Set Browser = CtrlBrowser.Object
Browser.Navigate "X:\" 'Actually some network-path related to my workbook-path
OleFrame.Activate
End Sub
The second option works somewhat OK but when I switch to another worksheet and return, my frame is empty and I can't get a valid reference to my "Browser" control.
Sub CheckFrame()
'
Dim CheckBrowser As Object
Set CheckBrowser = ActiveSheet.OleObjects(1).Object.Controls("Browser").Object
Stop
'CheckBrowser now actually contains the correct WebBrowser-object,
'but when I run this sub (after I return to my Worksheet
'with the Frame-OleObject) all it's properties either
'contain falsified data or may not be accessed by the debugger...
'Everything is fine, when I run this sub right after
'my AddOleFrameWithBrowser()-Sub.
ActiveSheet.OleObjects(1).Activate '<- Does not help
End Sub
Additionally whenever I try to do something with the folder-items inside my embedded explorer, it displays some security warning because the path is not on my local machine. This warning does not appear when I add the Shell.Explorer-OleObject directly with AddOleBrowser().
Could someone please give me some advice?
I'm looping through a list of csv files from a website which I want to open and extract the data from. The reason I'm using VBA is because the specific files I need to open varies day per day, and those specific file references is available only in an excel view. The second reason is because I've already made a similar scraping application in vba, so I already had half the code.
The end user of the application doesn't need clean or fast code, just that it works, because checking these files manually now is a daily chore of 2 hours per day.
So far I'm already logged into the website where the secondairy files are stored (This website has no API so I'm scraping it) and I'm opening those files by letting the code click the buttons. The code then clicks the export button, which opens the dialog box to
open, save (dropdown), cancel
I just want to open and extract the data then close, so I'm using the code from VBA Internet Explorer Automation - How to Select "Open" When Downloading a File . It feels like my code is bugging on this part...
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Dim ie As InternetExplorer
Dim h As LongPtr
Function Download()
Dim o As IUIAutomation
Dim e As IUIAutomationElement
Set o = New CUIAutomation
h = ie.Hwnd
h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString)
If h = 0 Then Exit Function
Set e = o.ElementFromHandle(ByVal h)
Dim iCnd As IUIAutomationCondition
Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "Open")
Dim Button As IUIAutomationElement
Set Button = e.FindFirst(TreeScope_Subtree, iCnd)
Dim InvokePattern As IUIAutomationInvokePattern
Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern.Invoke
End Function
before I invoke this function I check the amount of workbooks and make excel wait upto 20 seconds until another workbook is opened. I do that with this code
xnum1 = Application.Workbooks.Count
Download
t = Now
tStop = t + TimeValue("00:00:20") 'Adjust the TimeValue as needed "hh:mm:ss"
Do Until t = tStop Or Application.Workbooks.Count > xnuml
DoEvents
t = Now
Loop
However it seems that even with this wait time, excel doesn't want to open the file during every loop. If I run it step by step, it does open the file, when I let it run on it's own, it doesn't.
After I downloaded the file I export the data to the main file and then close it, using Application.DisplayAlerts to ensure no dialog box prevents the closing of the file. But because the code bugs in the download I've had instances where the file opened too late and then it didn't close, and because they all have the same filename I made an extra safegaurd in the main code:
xnum1 = Application.Workbooks.Count
For y = 1 To xnum1
If Left(Application.Workbooks(y).Name, 10) = "export.csv" Then
Application.Workbooks(y).Close
End If
Next
I can't seem to figure out why excel isn't opening the files properly and then closing them properly... Seems like the code just runs, goes into error mode because the file didn't open in the second run, although no error is given by the code itself even when I step through it.
My gut is telling me that this Download function is where the problem lies, but I can't point out how to fix it...
I've also tried with sendkeys %{O}, the shortkey to click open, but this also didn't open the file. When I manually click alt + O it does open the file...
Any suggestions?
I am dealing with a web form text field that will initiate a search on its contents, when "Enter" is pressed.
I know how to initiate all of the other event listeners but I am unable to get the press "Enter" event to trigger. It is not listed with the other events. i.e. onchange, onclick, onblur
I am using the CreateObject("Shell.Application") as the parent object in Excel VBA to control an existing IE browser.
I tried sendkeys but have trouble with what VBA focuses on. It types in my IDE or on the spreadsheet itself.
It is not a public site. It is an input tag with Events (blur, change, focus, keydown, mousedown, mousemove).
With Tex_Box
.focus
.keydown
.innertext = Field_Text
.change
.focus
.blur
End With
So I found that stackoverflow.com/questions/11655591/… describes how to provide Internet Explorer with focus before Sendkeys are used well. However, "how" was merely part of the puzzle, the other part was finding "what" needed focus before the program would invoke the sendkey "~"(Enter). Due to an unknown number of sendkey "{TAB}"'s that would have taken to land the cursor on the desired field, I created a loop that would continuously iterate through all the text fields until the partial-string "focus" was present in the attribute titled classname of the desired text box. Once that occurs, the program would have a marker to let it know to invoke the sendkey "~."
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Declare Function SetForegroundWindow Lib "user32" (ByVal HWND As Long) As Long
Dim HWNDSrc As Long
text_again:
With DOCK_Tex_Box
.focus
.keydown
.innertext = Field_Text
.change
Sleep (500)
.focus
.blur
HWNDSrc = IE.HWND
For i = 1 To 100
DoEvents
SetForegroundWindow HWNDSrc
DoEvents
Application.SendKeys ("{TAB}"), True
DoEvents
Sleep 1000
If InStr(.classname, "prompt") > 0 Then 'If the for loop goes to quickly the field loses focus and then the text clears out.
DoEvents
Sleep 500
GoTo text_again:
End If
If InStr(.classname, "focus") > 0 Then 'Text field has focus
Sleep 1000
Exit For
End If
Next
End With
Application.SendKeys ("~"), True
DoEvents
Sleep 500