I am trying to download a file from sharepoint via VBScript.
Unfortunately i get the following errormessage after downloading the Excel- File:
"Excel cannot open the file ' xxxxx.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file"
My code snipped is the following:
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", "https://company.sharepoint.com/:x:/r/teams/xxxxx/_layouts/15/Doc.aspx?sourcedoc=%7B5AA396CB-4711-4E73-AEC5-3CB8B6E174D3%7D&file=xxxx%20Automation%xxxx.xlsx&wdOrigin=OFFICECOM-WEB.START.REC&action=default&mobileredirect=true", False
xHttp.Send
with bStrm
.type = 1 '//binary
.open
.write xHttp.responseBody
.savetofile "c:\temp\TestNow.xlsx", 2 '//overwrite
end with
The approach isn't wrong but when dealing with downloads from a URL you should always check the Response Status Code to see if it is valid before continuing.
After calling Send() always surround the response in a conditional statement like this;
If xHttp.Status = 200 Then 'Expecting a HTTP 200 OK response
With bStrm
.Type = 1 '//binary
.Open
.Write xHttp.responseBody
.SaveToFile "c:\temp\TestNow.xlsx", 2 '//overwrite
End With
Else
'Check the response body for details of the error.
MsgBox("Unexpected response: " & xHttp.Status & " - " & xHttp.StatusText, 48, "Error")
End If
Because you are trying to download from a SharePoint site the likelihood is the request is failing and returning an HTTP 403 Forbidden for not providing any authentication.
Related
I have implemented a Sharepoint API connect/authorize/download functionality in an Excel workbook using VBA - see my implementation snippet below:
base_url = "SP URL/_api/web/"
end_url = "GetFileByServerRelativeUrl('" & endpoint_url
url = base_url & end_url & filepath & "')/$value"
HttpRequest.Open "GET", url
HttpRequest.setRequestHeader "Authorization", "Bearer " & auth_token
HttpRequest.Send
sresult = HttpRequest.responseText
sObject = HttpRequest.responseBody
filepath = Replace(filepath, "%20", " ")
filestring = Replace(filestring, "%20", " ")
'MsgBox HttpRequest.Status
If HttpRequest.Status = 200 Then
'MsgBox HttpRequest.responseBody
Set MyStream = CreateObject("ADODB.Stream")
MyStream.Open
MyStream.Type = 1
MyStream.Write HttpRequest.responseBody
MyStream.SaveToFile filestring, 2
MyStream.Close
Else
MsgBox HttpRequest.Status
MsgBox "Error - Connection to server failed"
End If
I am struggling with how to adapt this for an upload use case.
From reading the SP API docs I can see that I need to adjust the url endpoint to /GetFolderByServerRelativeUrl('/Library Name/Folder Name')/Files/add(url='example.txt',overwrite=true)
I am however unsure on the adaptation of the HttpRequest part, is it as simple as changing the `HttpRequest.Open "GET", url' to 'HttpRequest.Open "SEND", url' and then alterating the below part?
Set MyStream = CreateObject("ADODB.Stream")
MyStream.Open
MyStream.Type = 1
MyStream.Write HttpRequest.responseBody
MyStream.SaveToFile filestring, 2
MyStream.Close
I've been at this for a few hours now, have tried to rewrite the MyStream part of the script but I am really unfamiliar with constructing this type of upload request.
Have attempted to write a SEND version of the function but am unclear on the full scope of changes I need to make.
For upload use .LoadFromFile and then .read on the ADO stream.
' read file as binary
Dim ado As Object
Set ado = CreateObject("ADODB.Stream")
With ado
.Type = 1 'binary
.Open
.LoadFromFile filepath & filename
.Position = 0
End With
' request
Dim client As Object
Set client = CreateObject("MSXML2.XMLHTTP.6.0")
With client
.Open "POST", Url, False
.setRequestHeader "Authorization", "Bearer " & AUTH_TOKEN
.send ado.read
ado.Close
Debug.Print .responseText
If .Status = 200 Then '200 = OK
MsgBox ("Upload completed successfully")
Else
MsgBox .Status & ": " & .statusText
End If
End With
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 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