VB macro changing encoding on REST request - vba

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?

Related

Why do i get "Argument is not optional" error on simple url call?

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")

VBA GET request failing, bad format?

I'm a novice and your help has been amazing so far! I have an issue with a GET request for SSO authentication in an Excel Visual Basic script. The API says to send the GET request to:
https://services.example.com/API/Security.svc/SSOSiteLogin/siteId/enterpriseGuid/authToken/timezoneOffset
Where the values for siteID, enterpriseGUID, authToken, and timezoneOffset have all been obtained by previous GET requests, which have worked fine. When I send the final GET request for a security token, it returns:
{"Detail":"SSOSiteLogin failed.Input string was not in a correct format."}
Here is my relevant code:
Dim hreq As New WinHttpRequest
Dim response As String
Dim URL As String
'get security token
URL = "https://services.example.com/API/Security.svc/SSOSiteLogin/siteID/enterpriseGUID/" & authToken & "/null"
hreq.Open "GET", URL, False
hreq.Send
response = hreq.ResponseText
Range("A13") = response
The siteID and enterpriseGUID variables are input into the code, and the authToken is stored from an earlier POST request. The last value, timezoneOffset, is given as "null" from an earlier request so I've been typing "/null" at the end but I'm concerned that's what's triggering the incorrect format response. Anything else just returns a total error from the server though.
Any ideas? Thank you in advance!
I had put the values into cells and was sending the GET request as "Range("E5") & "/" & Range("E6") & "/", etc. so that I could try a couple of debugging issues without having to go to the VBA editor and for some reason that worked! I ended up using the string "null", too. If anyone knows why this worked and inputting it all as one string doesn't I'd be interested to find out.

ASPTwitter library fails when using special characters

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

Reading HTML file in VBA Excel

i want to read the HTML code in VBA (something like URL in Java). I need to save it in a string. I parse it afterwards.
alpan67
Here's a function for you. It will return the String of the HTML returned by a given URL.
Function GetHTML(URL As String) As String
Dim HTML As String
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.Send
GetHTML = .ResponseText
End With
End Function
Just make sure your provided URL is well formed. I.E. it includes the http:// or https:// if appropriate.
For Example: GetHtml("www.google.com") is incorrect. You would want GetHtml("https://www.google.com/")
To do the URL DECODING you may use that post as a reference.
Here goes a article that uses MS Word to save html of web page as text.
Code in Excel VBA - from VBAExpress: I wouldn't fancy copying his code. You may give it a try and comment.

How to write to a "Google Spreadsheet" from Excel 2003 VBA

I Have an Excel 2003 file with a line similar to this:
I need to click "the button" and it adds that line as the last one on a Google Spreadsheet
Similar to:
Is it possible?
Should I use the command-line Google tools?
Is there a better way? Easier way?
How would you do it?
(once I know how to add "stuff" from VBA to Google Docs, how the f do i add it to the last line?)
More info: I have an Excel 2003 "program" that saves all of the company's sales (with the customer info), and I'd like do make a global address book that's easily updated by my (non it) co-workers.
You don't need OAuth or the spreadsheet API. Google Spreadsheet allows data entry with a simple form, which means also that a HTTP POST will do the trick. You just need to prepare your spreadsheet to accept data entries via a form as follows:
Login to your Google Docs account
Create a spreadsheet or open an existing one
Click on Tools / Create a form
Add anything in the form description just to enable the Save button
Save the form
Copy the formkey value displayed in the link at the bottom of the form creation page
Now you can issue a simple post into the spreadsheet without OAuth
You can test the entry now with curl if you have it on your system (replace the formkey placeholder with the formkey from your table):
curl.exe -v -k "http://spreadsheets.google.com/formResponse?formkey=<formkey>" -d "entry.0.single=test&entry.1.single=test2&pageNumber=0&backupCache=&submit=Submit"
Next we try to execute the form POST from our Excel sheet via the following code. Add a reference to "Microsoft XML, v3.0" before. Replace column1 with your desired values.
Dim httpRequest as XMLHTTP
Set httpRequest = New XMLHTTP
httpRequest.Open "POST", "http://spreadsheets.google.com/formResponse?formkey=<formkey>&ifq", False
httpRequest.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
httpRequest.Send "entry.0.single=" + column1 + "&entry.1.single=" + column2 + "&pageNumber=0&backupCache&submit=Submit"
'Check result in the following vars
httpRequest.status
httpRequest.statusText
Hope that helps
I had started answering your question, but realized that it was much less trivial than I thought it was when I started playing with the OAuth 2.0 API. I think it would be a lot easier if you could make your Google spreadsheet public, but I doubt that is advisable with sales data.
The reason this is non-trivial is the authentication part. The ASP OAuth below is probably usable with some work, but I noticed it uses Session variables and some other ASP objects, so you'd have to do a lot of tweaking.
In that light, here is my original answer, if it helps.
There is a google spreadsheet API:
https://developers.google.com/google-apps/spreadsheets/#adding_a_list_row
The OAuth 2.0 link that the spreadsheet docs refer to is out-of-date. You can play with the OAuth requests here, which should help you get started.
API functions are called by GET/POST requests with XML, which you can call using the XMLHTTP object.
First, reference Microsoft XML in your Excel project (Tools->References->Microsoft XML, v6.0)
In your VBA, you essentially use the following to send XML requests:
Dim x as MSXML2.XMLHTTP
Set x = New MSXML2.XMLHTTP
x.Open "POST", "http://example.com/", False
x.Send "<xmldata></xmldata>"
You should be able to adapt this OAuth 2.0 ASP library for your VBA code.
This is an ASP example of how to use that OAuth library; again since both the ASP and the VBA are using the VBScript syntax, it could probably be adapted.
I spent the last couple of days trying to find a good easy solution to this problem.
None seemed to work for me so I had to utilize bits and pieces from various posts I found on-line.
Steps to follow:
Create a Google spreadsheet
Create a form (under “Tools” – “Create a form”) with a three fields (you can add fields later after testing)
Go back to the Google spreadsheet and it should have created a new sheet (called "Form Responses") with headings matching the field names given when setting up the form.
Column A will automatically have as a heading “Timestamp” with your field names as headings for columns B, C & D etc.
Now click on “Form” – “Go to Live Form”
Write-click and “Inspect” (Ctrl-Shift-I) and click on Network
Enter some data (anything) for each of the respective fields and click on “Submit”
Click on “Headers” Click on “formResponse”.
Under “General” copy the url of the form. Note a “?” is required at the end of the url.
Also under headers find “Form Data”. This will be used in MyURL
Look for the entry.123456789 for each of the fields.
You will need these numbers for each field.
Replace xxxxxxxx in your code with your form's respective numbers.
Open up your Excel spreadsheet and copy in the sub-routine shown below
In the VBA editor click on Tools – References select the Microsoft XML.v3.0, (Microsoft XML Core Services)
Code:
Sub Write_Info_To_Google()
Dim ScriptEngine
Dim http As Object
Dim myURL As String
Set http = CreateObject("MSXML2.ServerXMLHTTP")
Set ScriptEngine = CreateObject("MSScriptControl.ScriptControl")
ScriptEngine.Language = "JScript"
ScriptEngine.AddCode "function encode(str) {return encodeURIComponent(str);}"
myURL = "https://docs.google.com/forms/d/e/ . . . . /formResponse?" & _
"entry.xxxxxxxxx=" + Cells(2, 1).Text + _
"&entry.yyyyyyyyy=" + Cells(2, 2).Text + _
"&entry.zzzzzzzzz=" + Cells(2, 3).Text
http.Open "GET", myURL, False
http.setRequestHeader "User-Agent", "Google Chrome 70.03538.102 (compatible; MSIE _
6.0; Windows NT 5.0)"
http.send
End Sub
Run this macro and watch your data from row 2 appear in the Google spreadsheet
Rather than use VBA in Excel, use a full fledged VB.NET application with the Excel Interop COM package. It's syntax is largely similar to the VBA commands, but to do the transferring to Google docs will be much easier in VB.NET.
Use the Google Documents List API to create a new spreadsheet.
Use the Google Spreadsheets API to move the data into your online spreadsheet.
Both Google APIs are REST APIs, so you'll have to use HttpRequest objects in VB.NET. Here is a great example of how to use them, just change the URLs so they are appropriate for Google. Google Spreadsheets even offers a library that abstracts away many of those steps.