I am new to VBA so this is probably my problem. I am trying to perform a HTTP POST from Excel to a web service, and I can POST quite happily, until I change the code so that I am posting content in my message, at which point I get the following error:
Run-time error '-2147024809 (80070057)':
The Parameter is incorrect.
My code is as follows:
Dim oHttp As Object
Set oHttp = CreateObject("MSXML2.XMLHTTP.6.0")
Call oHttp.Open("POST", url, False)
oHttp.setRequestHeader "Content-Type", "application/text"
oHttp.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
Call oHttp.send(content)
httpPOST = oHttp.responseText
The line which is killing the code is the oHttp.send - if I do not pass any content then it is fine, as soon as I put content here it is unhappy.
The content parameter is a large string containing comma separated text and includes line feeds. I think this is why it is unhappy, if I change the string to simply a short "Hello" then the send is sucessful and the application happily makes it to the next line, before hitting the run-time error:
The data necessary to complete this operation is not yet available
So I guess my question is, how do I POST a large block of text to a server?
Thanks
Thanks for the comments, I managed to get it to work by converting the string to a binary array and then send the binary array over.
Related
I have an excel file with a button associated to a VB macro like this:
Sub button_macro()
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
MyRequest.Open "GET", "http://theurl/service?param=""Gestión"""
MyRequest.Send
End Sub
But the response I get is something like:
"Gestión" is not a valid value for param.
How can I avoid VB converting the 'ó' character to another encoding?
If I send the request via browser like:
http://theurl/service?param="Gestión"
The service answer as desired.
EDIT:
Curiously MsgBox "Código único" works as expected showing the 'ó' and 'ú' characters correctly.
It works in the browser because the browser encodes the request for you - you can see that if you use your browser's Developer tools - eg for your "example" URL of
http://theurl/service?param="Gestión"
I see
http://theurl/service?param=%22Gesti%C3%B3n%22
You can encode your parameters using (eg) the UTF-supporting method from the accepted answer here: How can I URL encode a string in Excel VBA?
My goal is to check the internet connecton in VBA but when i try to call a url with request.open I get the error message "Argument is not optional".
Sadly internet research has no yielded any results.
This is my code:
On Error GoTo NoConnectionErrorHandling
Dim Request As MSXML2.XMLHTTP60
Request.Open "http://www.google.com"
Request.send
MsgBox Request.Status
It hangs itself in the third line of the shown code.
I hope someone can help me as i have very very little experience in VBA yet.
You have to specify the type of the request. It can be "GET", "POST" or something else.
See here for the open Method:
https://msdn.microsoft.com/en-us/library/ms757849(v=vs.85).aspx
These are the parameters:
bstrMethod
The HTTP method used to open the connection, such as GET, POST, PUT, or PROPFIND. For XMLHTTP, this parameter is not case-sensitive. The verbs TRACE and TRACK are not allowed when IXMLHTTPRequest is hosted in the browser. What is the difference between POST and GET?
bstrUrl
The requested URL. This can be either an absolute URL, such as "http://Myserver/Mypath/Myfile.asp", or a relative URL, such as "../MyPath/MyFile.asp".
varAsync[optional]
bstrUser[optional]
bstrPassword[optional]
As you see, the method needs at least two parameters (the other 3 are optional) thus 1 is not enough.
You need to declare Request with the keyword New. Thus, something like the following piece works:
Public Sub TestMe()
Dim Request As New MSXML2.XMLHTTP60
Request.Open "GET", "http://www.bbc.com"
Request.send
MsgBox Request.Status
End Sub
Whenever you are using libraries outside the standard VBA libraries it is a good idea to do one of the following 2:
Provide information for the library:
Use late binding:
Dim Request As Object
Set Request = CreateObject("Msxml2.ServerXMLHTTP.6.0")
So, I have this spreadsheet with a list of about 5000 URLs. (All pages on our corporate intranet.)
We know some of the links are broken, but don't know of a good way to determine which without clicking all 5000 links.
Normally this would be a simple matter: Create a web page with links to the 5000 pages, and then check the links with a tool like Xenu Link Sleuth.
But that won't work in this case because many of the links are being redirected, and the redirect code spoofs HTTP.response 200, which tricks Xenu into treating it as a valid URL.
However, there is some good news: The redirect script does not run from within Excel. If you click a bad link inside Excel, the redirect script does not execute and the HTTP response is reported back to Excel. I believe Excel should be able to identify the correct HTTP response code (404) - or at least whether the link was valid or not.
Which brings me to my question:
Is there a way using VBA to write a script that would click through every link and capture the result? The result captured could be in the form of the HTTP response code or anything else you think would be useful in finding the bad links in this list of 5000 pages. Ideally the result would be written to a cell in the spreadsheet adjacent to the link.
If anyone if familiar enough with VBA to suggest a solution to this problem, I would be eternally grateful!
Here is an example to check the status line from a list of URL with Excel:
Sub TestLinks()
Dim source As Range, req As Object, url$
Set req = CreateObject("Msxml2.ServerXMLHTTP.6.0")
' define were the links and results are
Set source = Range("A1:B2")
' clear the results
source.Columns(2).Clear
' iterate each row
For i = 1 To source.Rows.count
' get the link from the first column
url = source.Cells(i, 1)
' send the request using a HEAD to check the status line
req.Open "HEAD", url, False
req.setRequestHeader "Accept", "image/webp,image/*,*/*;q=0.8"
req.setRequestHeader "Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6"
req.setRequestHeader "Accept-Encoding", "gzip, deflate"
req.setRequestHeader "Cache-Control", "no-cache"
req.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
req.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"
req.Send
' write the result in the second column
source.Cells(i, 2) = req.Status
Next
MsgBox "Finished!"
End Sub
Use a user defined function to return HTML-Status Codes and drag it down next to the links. Might take a while for Excel to check 5000 links, though.
Public Function CheckURL(url As String) As String
Dim request As New WinHttpRequest
request.Open "GET", url
request.Send
CheckURL = request.Status
End Function
You will probably need to add a reference to "Microsoft WinHTTP Services" under "Extras" -> "References"
I want to connect to a Cloudant database from an Excel Macro that I have written. The macro would essentially need to find data in a specific field searching on another field. Example: For ID="2", return data in field "Name". Does anyone know how this is possible?
Thanks.
Edit: I have posted an answer to my own question. The answer I posted gets all docs from a specified database. From here you can query, etc. to get the specific data you are looking for. You can also use an excel macro JSON parser, found here to help sort through the data. The Base64Encoder I used can be found here.
From the documentation:
All requests to Cloudant go over the web, which means any system that can speak to the web, can speak to Cloudant. All language-specific libraries for Cloudant are really just wrappers that provide some convenience and linguistic niceties to help you work with a simple API.
Now, to your question:
Does anyone know if/how this is possible?
VBA capable of sending and receiving HTTP requests, ergo, this is possible using Excel (or any other application that can run VBA).
In case anyone else ever searches for this, I figured I would upload an actual response to this question (nearly a month later) rather than just a "yes, this is possible".
Since Cloudant requires Basic Auth, the way that I have found to do this is below:
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
Dim response As String
'Sameple URL: https://ibmcds.cloudant.com/sandbox/_all_docs
URL = "https://" + CloudantUsername + ".cloudant.com/" + DatabaseName + "/_all_docs"
With objHTTP
.Open "GET", URL, False
.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.SetRequestHeader "Content-Type", "application/json"
.SetRequestHeader "Accept", "application/json"
.SetRequestHeader "Authorization", "Basic " + Base64Encode(CloudantUsername + ":" + CloudantPassword)
.Send ("")
End With
response = objHTTP.responseText
In this example, the Base64Encode function just encodes the given string. You can use any Base64 Encoder for this.
And if you want to check the status of the request you can use:
If objHTTP.Status = 200 Then
response = objHTTP.responseText
MsgBox "This request is valid.", vbOKOnly
Else
MsgBox "This request is not valid.", vbOKOnly
End If
Or something similar.
I hope this helps anyone else who may be looking to do something like this.
I am trying to update an old ASP classic Twitter program that my work currently uses to use the new OAUTH. I am not an ASP programmer but I managed to find the ASPTwitter library posted online by Tim Acheson at http://www.timacheson.com/Blog/2013/jun/asptwitter
Everything works, as we have our own code searching our database and passing on a built string to the ASPTwitter code to tweet.
The catch is that it will fail with the
{"errors":[{"message":"Could not authenticate you","code":32}]}
error message if there is so much as a "." period in the string. Every possible special character besides letters and numbers causes a fail.
We have many posts that will include various symbols as well as URLs.
I have searched all over and have not been able to find a solution. Comments on Tim's site have mentioned it but no solutions yet. Everyone here has been very helpful so I was hoping someone might have a solution.
I can't post the code as there are about 6 files and I don't know which one is causing the issue.
Thank you so much for the help!
Edit:
This is a block of the 300+ line file where the issue happens, I hope that the cause can be found here too.
' Gets bearer token for application-only authentication from Twitter API 1.1.
' Application-user authentication: https://dev.twitter.com/docs/auth/using-oauth
' and: https://dev.twitter.com/docs/auth/authorizing-request
' API endpoint statuses/update (post a tweet): https://dev.twitter.com/docs/api/1.1/post/statuses/update
Private Function UpdateStatusJSON(sStatus)
Dim sURL : sURL = API_BASE_URL + "/1.1/statuses/update.json"
Dim oXmlHttp: Set oXmlHttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
oXmlHttp.open "POST", sURL, False
sStatus = "this is from the ASPTwitter dot asp file"
oXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
oXmlHttp.setRequestHeader "User-Agent", "emiratesjobpost.com"
oXmlHttp.setRequestHeader "Authorization", "OAuth " & GetOAuthHeader(sURL, sStatus)
oXmlHttp.send "status=" & Server.URLEncode(sStatus) ' Encoded spaces as + in request body.
UpdateStatusJSON = oXmlHttp.responseText
Set oXmlHttp = Nothing
REM: A JSON viewer can be useful here: http://www.jsoneditoronline.org/
' To fix error message "Read-only application cannot POST" go to your application's "Application Type" settings at dev.twitter.com/apps and set "Access" to "Read and Write".
' After changing access to read/write you must click the button to generate new auth tokens and then use those.
Response.Write "<textarea cols=""100"" rows=""3"" >" & UpdateStatusJSON & "</textarea>" : Response.Flush()
End Function
If I replace the "dot" with "." in the "sStatus" line, it breaks
Do your pages use UTF-8 encoding? Open them in Notepad, select save as from the file menu, and if ansi coding is selected then change it to UTF-8.
See this link for more things you can do
http://www.hanselman.com/blog/InternationalizationAndClassicASP.aspx