So I have a VBA code that is currently successfully logging into a website and further navigating to other pages of the website and scraping data that I need.
I now need to navigate to a page (no problem), fill a textbox with a query (no problem) and click on a 'download' button (no problem). This then prompts a popup to download a file (open/save/cancel). My requirement is to save this file without user interaction - the macro should save the file in a predetermined directory.
Any ideas on how to achieve this? I couldn't get SendKeys to work at all.
Set appIE = New InternetExplorerMedium
sURL2 = "http://somewebsite.com/query.asp?"
With appIE
.Navigate sURL2
.Visible = True
End With
Do While appIE.Busy Or appIE.ReadyState <> 4
DoEvents
Loop
'code to enter the query in textbox and click on download file button
appIE.Document.getElementsByTagName("textarea")(0).Value = Sheets("UserEntry").Range("L37")
appIE.Document.getElementsByName("btnSubmit")(203).Click
Application.SendKeys "%{s}"
Set appIE = Nothing
Edit: Even if I could get SendKeys to work, I need to 'save as' the file automatically, not just 'save' it in the Downloads folder.
Ok, got it working, thanks to the approach suggested by #BrownishMonster
I used WinHTTP.WinHTTPRequest.5.1
I also used Fiddler to investigate what the browser was sending in the POST requests and then made VBA do the same
Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")
'This is to POST the login info and login to the site
WHTTP.Open "POST", mainUrl, False
WHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.send loginString
'This is to POST the download info and download the file
WHTTP.Open "POST", fileUrl_XLSResult, False
WHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.send downloadString
FileData = WHTTP.responseBody
'This is to save the file in the location MyFilePath
If WHTTP.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WHTTP.responseBody
oStream.SaveToFile MyFilePath, 1
oStream.Close
End If
Related
I want to download a zip file from OneDrive using VBA.(UserData folder zipped as UserData.zip and uploaded to the OneDrive location; size: 200KB) For that, I used the following VBA script.(sensitive data altered in the code)
Sub DownloadFile()
'Declare the Object and URL
Dim myURL As String
Dim WinHttpReq As Object
'Assign the URL and Object to Variables
myURL = "https://MYCOMPANYNAME-my.sharepoint.com/personal/MYUSERNAME_MYCOMPANYNAME_com/Documents/FOLDERNAME/UsersData.zip"
Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
'Provide Access Token and PWD to the URL for getting the service from API
WinHttpReq.Open "GET", myURL, False, "abcdef", "12345"
WinHttpReq.send
Debug.Print WinHttpReq.Status
myURL = WinHttpReq.responseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.responseBody
oStream.SaveToFile "C:\Users\MYUSERNAME\Downloads\UsersData.zip", 2
oStream.Close
MsgBox "File downloaded"
Else
MsgBox "Download failed"
End If
End Sub
When I run it, it downloads the zip file and gives me the "File downloaded" message as well. But when I try to open the downloaded file, unzipping application fails to do that and it seems like the file is corrupted.
This works fine for pdf, jpg, txt and other similar files. Why this happens only in zip files?
What is the issue in my code and is there any other effective ways in VBA to download zip files from OneDrive?
My Excel VBA macro sends a POST multipart/form-data request to an API and receives a application/pdf file as a response.
This is the relevant part:
Set xhr = CreateObject("MSXML2.XMLHTTP")
xhr.Open "POST", Uri, False
xhr.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & strBoundary
xhr.setRequestHeader "X-Api-Key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
xhr.send (strBody)
If xhr.Status Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write xhr.responseBody
oStream.SaveToFile outputFileName, 2
oStream.Close
End If
Set xhr = Nothing
The downloaded PDF document is unreadable by any PDF reader. I checked its contents and it is almost the same as the downloaded document from other clients (eg Postman, cURL), which are valid PDF documents (ie can be open in PDF readers) [Edited].
For example, when opening the PDF documents in VS Code:
The VBA macro downloaded file:
Compare it to the PDF downloaded with Postman (Check the last line in the picture):
If it was a text file, it would seem as an encoding problem, but as I am using the ADODB.Stream with Type = 1 that should handle binary files well.
What am I missing?
I have searched for a solution to this issue having first researched via Mr Excel and also elsewhere on this site (specifically question 22051960 which appears to be closed to new users like me).
The site I am attempting to download from is :
https://downloads.theice.com/
and it appears that the main site is an html page requesting authorisation credentials.
I have tried the code the above referenced thread which appears to successfully open the main site, authenticate and save the file; however, when I navigate to the file it is not the file on the site but is instead only 1kb and not in excel format. Here is the code from that thread:
Sub SaveFileFromURL()
Dim FileNum As Long
Dim FileData() As Byte
Dim WHTTP As Object
mainUrl = "https://downloads.theice.com/"
fileUrl = "https://downloads.theice.com/Settlement_Reports/Oil/icecleared_oil_2017_01_24.xlsx"
filePath = "C:\mydownloads\myfile2.xls"
myuser = "username"
mypass = "password"
'#David Zemens, I got this by examining webpage code using Chrome, thanks!
strAuthenticate = "start-url=%2F&user=" & myuser & "&password=" & mypass & "&switch=Log+In"
Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")
'I figured out that you have to POST authentication string to the main website address not to the direct file address
WHTTP.Open "POST", mainUrl, False 'WHTTP.Open "POST", fileUrl, False
WHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.Send strAuthenticate
'Then you have to GET direct file url
WHTTP.Open "GET", fileUrl, False
WHTTP.Send
FileData = WHTTP.ResponseBody
Set WHTTP = Nothing
'Save the file
FileNum = FreeFile
Open filePath For Binary Access Write As #FileNum
Put #FileNum, 1, FileData
Close #FileNum
MsgBox "File has been saved!", vbInformation, "Success"
End Sub
I have reasonable vba skills within excel but have no experience of html or web-page functionality and so am lost as to how to resolve this issue.
My ultimate aim is to utilise the authentication code within a routine I have written which automatically saves files from a list of URL's in an excel spreadsheet which already works for non-protected url's.
I hope this is an acceptable question for this forum
Many thanks
In my opinion, you should set the credentials (SetCredentials method) before sending your request on your WinHttpRequest instance.
Something like this
WHTTP.SetCredentials(myuser , mypass , HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);
Could you also have a look on below links?
https://msdn.microsoft.com/en-us/library/aa384058(VS.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa383144(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384076(v=vs.85).aspx
I hope this will help you
i have tried the following code to download a single Excel file from Sharepoint 2013.
Option Explicit
Sub TxtStream()
Dim myURL As String, DestFile As String, myHeader As String
Dim Usr as string, Pwd as string
Dim oStream As Object
Usr="": Pwd=""
myURL = "https://Server.Name/teams/Forms/AllItems.aspx/MasterFile.xlsx"
DestFile = "C:\Test.xlsx"
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("MSXML2.XMLHTTP")
'WinHttpReq.Open "HEAD", myURL, False, Usr, Pwd
'WinHttpReq.Send
'myHeader = WinHttpReq.getAllResponseHeaders()
'Debug.Print myHeader
'myHeader = WinHttpReq.getResponseHeader("Content-Disposition")
'Debug.Print myHeader
'myHeader = WinHttpReq.getResponseHeader("Content-Type")
'Debug.Print myHeader
WinHttpReq.Open "GET", myURL, False, Usr, Pwd
WinHttpReq.setRequestHeader "content-type", "application/octet-stream"
WinHttpReq.Send
myURL = WinHttpReq.responsebody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Type = 1
oStream.Open
oStream.Position = 0
oStream.Write WinHttpReq.responsebody
oStream.SaveToFile DestFile, 2
oStream.Close
End If
End Sub
It downloads ok, but when i try to open it in Excel 2010, it shoots an error:
Excel cannot open the file Test.xlsx because the file format or file extension is not valid. Verify the file has not been corrupted and the file extension matches the format of the file.
I have checked the Content-Type and it shows as Text/Html;UTF-8. It doesn't show Content-Disposition.
Can someone help as to why the file is not opening?
This is not a full fledged answer, but more like a comment / suggestion as I do not have enough reputation to post comments.
Setting a content-type header in your GET query does not seems to make any difference. We need to check the WinHttpReq.getResponseHeader("Content-Type") sent by the server which in this case seems to be Text/Html;UTF-8.
If you copy paste the URL used in myURL variable to your browser, do you get the "file save as" dialog box?
Better analysis of your requests and responses can be done if you use Fiddler Web Debugger where you can create requests in teh composer and check the responses to finetune your requirements and to see whether any other headers (like cookies, authentications etc) are also required for the file to be downloaded. In this case, you might be getting back a login page (html) because of some authentication issues and not the excel file.
Open the DestFile saved with Notepad.exe to see whether it is actualy an XLSX file (starting with characters PK) or an HTML or other text file.
I am doing a VBA module in which I want to download the csv file from google finance.
Here is a sample URL
www.google.com/finance/historical?q=LON%3AESSR&ei=dEfGU_ioD4iKwAO3-4HQDg&output=csv
Once I put this URL in browser I get a csv file downloaded. But When I use the "WinHttpReq" object to download the file, I am not getting the csv file. Instead I am getting some HTML.
Is there anyway for me to download this CSV file using the URL in VBA?
Thanks,
Arun.
I am not familiar with WINHTTP but I seem to get this working fine - with XMLHTTP. Just enter your file path & name where commented
Sub getCSV()
Dim xhr As Object
Set xhr = CreateObject("MSXML2.XMLHTTP")
xhr.Open "GET", "http://www.google.com/finance/historical?q=LON%3AESSR&ei=dEfGU_ioD4iKwAO3-4HQDg&output=csv", False
xhr.send
With xhr
If .Status = 200 And .ReadyState = 4 Then
myfile = FreeFile
'HERE
Open "FILE_PATH_&_NAME.csv" For Output As #myfile
Print #myfile, .responseText
Close #myfile
Set xhr = Nothing
End If
End With
End Sub