Requesting URL with UTF-8 characters from VBA code - html

I am requesting results from this API:
http://mlrs.research.um.edu.mt/resources/gabra-api/
Everything works fine except when I introduce Maltese characters (which are UTF-8).
If I manually request the data using the following URLs, the return is correct.
http://mlrs.research.um.edu.mt/resources/gabra-api/lexemes/search?s=għar
...search?s=ċar (can't post more than two links yet.)
When using the following code, the return is blank.
{"results":[],"query":{"page":1,"page_size":20,"result_count":0,"term":"g?ar","search_lemma":true,"search_wordforms":true,"search_gloss":true,"pending":false,"pos":null,"source":null}}
{"results":[],"query":{"page":1,"page_size":20,"result_count":0,"term":"?ar","search_lemma":true,"search_wordforms":true,"search_gloss":true,"pending":false,"pos":null,"source":null}}
Note ? replacing ħ and ċ characters - that's only because I copied these from the immediate window.
This is the code I am using to make the requests:
Public Function GetWebSource(ByRef Url As String) As String
Dim xml As IXMLHTTPRequest
On Error Resume Next
Set xml = CreateObject("Microsoft.XMLHTTP")
With xml
.Open "GET", Url, False
.send
GetWebSource = .responseText
End With
Set xml = Nothing
End Function
Because VBA IDE does not support these characters, tests will need to be done from a form field.
Any help, much appreciated.
Thanks in advance.
Stephen

The URL contains some non ASCII characters, so you'll have to encode them beforehand:
Set xhr = CreateObject("Microsoft.XMLHTTP")
xhr.Open "GET", "http://mlrs.research.um.edu.mt/resources/gabra-api/lexemes/search?s=g%C4%A7ar", False
xhr.Send

Related

VBA and json objects

I want to create meail merge letters to members of a community, reminding them of the new year and to pay their fees. There is a nice API on a server that can create QR-codes that the a phone pay app can read. The server responds to HTTP POST rewuests. This API provides the possibility to pre-fill in the payment parameters like the payment receiver, the amount an a message to the payment receiver.
I am starting from an Excel-sheet that keeps the list of members amongst other items. I can create mail merge letters from this member list, but fails to get the creation of the prefilled QR-codes work correctly.
Since the base is Excel (and Word for the mail merge) the language used is VBA. With the code below i can get response from the server with a prefilled QR-code that contains the recieiver number of the payment:
Sub DownloadQRCode(ByVal myURL As String, ByVal LocalFileName As String)
Dim msXML As New MSXML2.ServerXMLHTTP60
Dim myStream As New ADODB.Stream
msXML.Open "POST", myURL, False
msXML.setRequestHeader "Content-Type", "application/json"
msXML.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
msXML.send "{""payee"":""987654321""}"
If msXML.Status = 200 Then
myStream.Open
myStream.Type = adTypeBinary
myStream.Write (msXML.responseBody)
myStream.SaveToFile LocalFileName, adSaveCreateOverWrite
myStream.Close
End If
Set msXML = Nothing
Set myStream = Nothing
End Sub
If I change the msXML.send statement to
msXML.send "{""message"":{""value"":""Sven_Svensson"",""editable"":""false""}}"
I get the response code 400 (Bad request)
The speicification for the message object looks like this
My questions are: Do I use the wrong value in "Content-Type" header or is the json representation of the message object faulty?
SOLVED!
A couple of mistakes from my side:
Phone/account numbers must be valid in this application
Booleans must not be quoted
Numbers must not be quoted
json uses brackets for arrays, not as outer paranthesis
I have this working fine now
This works for me:
msXML.send "{""payee"":""987654321"",""message"":{""value"":""Sven_Svensson"",""editable"":true}}"
Note booleans in JSON are not quoted.
You used an array ([]) in your message 'msXML.send "{""message"":[{""value"":""Sven_Svensson"",""editable"":""false""}]}"' while message's specification doesn't state it. I guess it should look like 'msXML.send "{""message"":{""value"":""Sven_Svensson"",""editable"":""false""}}"'

Unable to GET a value associated to div Tag <div class="name"> Value </div>

I'm using VBA to pull a value from a nested Div Tags, as shown on below image:
HTML code:
<div class="styles__SCFileModuleFooter-e6rbca-1 kUUNkj">
Constituída em 26-02-1962
</div>
I'm using the code Below to access class="styles__SCFileModuleFooter-e6rbca-1 kUUNkj", and pull the value "Constituída em 26-02-1962", but seems it is not capable to find that class in the loop:
Dim XMLPage As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument
Dim htmlEle1 As MSHTML.IHTMLElement
Dim htmlEle2 As MSHTML.IHTMLElement
Dim URL As String
Dim elemValue As String
URL = "https://www.informadb.pt/pt/pesquisa/?search=500004064"
XMLPage.Open "GET", URL, False
XMLPage.send
HTMLDoc.body.innerHTML = XMLPage.responseText
For Each htmlEle1 In HTMLDoc.getElementsByTagName("div")
Debug.Print htmlEle1.className
If htmlEle1.className = "styles__SCFileModuleFooter-e6rbca-1 kUUNkj" Then
elemValue = Trim(htmlEle1.innerText)
If InStr(UCase$(elemValue), "CONSTITU") > 0 Then
'Found Value
Exit For
End If
End If
Next htmlEle1
There are some cases where the class="styles__SCFileModuleFooter-e6rbca-1 kUUNk" appears more than once, that's the reason for the checking If InStr(UCase$(elemValue), "CONSTITU") > 0 Then.
Can anyone help please?
You are not capturing what actually happens when you use a browser to make that search.
Among the various steps are the following ones:
You navigate to https://www.informadb.pt/pt/pesquisa/?search=500004064
Webpage generates additional traffic
Amongst that additional traffic is an API POST XHR request which returns search results as JSON. That request goes to https://www.informadb.pt/Umbraco/Api/Search/Companies and includes the 500004064 identifier amongst the arguments within the post body
Based on the API results the browser ends up at the following URI https://www.informadb.pt/pt/pesquisa/empresa/?Duns=453060832
You are not ending up at this same endpoint, where you would find the target class, as JavaScript does not run with your XMLHTTP request, and thus the additional traffic is not generated.
You might try recreating the POST request which returns the necessary Duns value to take you to the same endpoint. The POST request response is as follows:
{'TotalResults': 1,
'NumberOfPages': 1,
'Results': [{'Duns': '453060832',
'Vat': '500004064',
'Name': 'A PANIFICADORA CENTRAL EBORENSE, S.A.',
'Address': 'BAIRRO DE NOSSA SENHORA DO CARMO,',
'Locality': 'ÉVORA',
'OfficeType': 'HeadOffice',
'FoundIn': None,
'Score': 231.72766,
'PageUrl': '/pt/pesquisa/empresa/?Duns=453060832'}]}
You can see the necessary Duns value in the response. You would need to parse out this value possibly with a JSON parser.
However, a quick look at how the server responds to requests seems to indicate it expects to receive JSON and not simply as a string. This rules out typical XHR/WinHttp request examples you will find on the web, though you might have some luck with the implementation via https://github.com/VBA-tools/VBA-Web. However, I have found that library to constantly throw errors when I have tried using it.
With Python, for example, you can easily just POST a JSON object specifying json = data within the requests.post() call if using requests library.

how to send JSON string to WCF using VBA

trying to send a POST to WCF services that accepts JSON string based on the website's JS. I had no luck buy just copy and paste the JSON string in an excel cell and use VBA's XMLHTTP60 to post. Always get bad data (status 400).
tried JSON string and JSON in cell doesn't work. I tried different JSON encoding doesn't seem to work either.
anyidea how I would post a JSON String to WCF?
My guess is somehow the VBA string loses its format during the request. Or different character code \ and : was send.
{"country":"{\"name\":\"USA\",\"population\":\"10000\"}\"}
{"country":"{"name":"USA","population":"10000"}"}
my VBA code
Sub test()
Dim XMLRequest As New MSXML2.XMLHTTP60
website = "URL"
postdata = thisworkbook.worksheets("Sheet1").range("A1").value
XMLRequest.Open "POST", "webSite", False
XMLRequest.SetRequestHeader "Content-Type", "application/json; charset=UTF-8"
XMLRequest.send postdata
end sub
However, I can use a browser console to send the AJAX with no problem.
var data=JSON.Stringify('{"country":"{"name":"USA","population":"10000"}"}');
$Ajax({
method: "POST",
URL: URL,
dataType:json,
contentType: "application/json; charset=UTF-8",
data:data,
cache: false
})
or I have no problem sending javascript in VBA via IE object
IE.Document.parentWindow.execScript "ajax call","javascript"
but my ultimate goal is to bypass IE, since it is not stable especially controlling through VBA.

How to make REST call to Content-Type="application/json" via VBA in Excel?

I'm using Google Chrome REST API to get information from my web server.
I use: Content-Type = "application/json"
and a Post command that includes groovy code inside the Payload (the header remains empty):
{
"aaa": "dan",
"bbb": "my_data",
"ccc": "my_type"
}
or sometimes the Post is empty also in the Payload
This works just fine (I'm getting the response in json format)
I want to post this command with VBA from excel so the response would get into a VBA variable, which I can then print into some cell in the worksheet. How do I do it?
Do I need to download some library for that?
I tried (without success):
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
URL = "[my_URL]"
objHTTP.Open "POST", URL, False
objHTTP.setRequestHeader "Content-type", "application/json"
Worksheets("sheet1").Cells(1, 1)=objHTTP
Please advise,
Needed to add:
objHTTP.setTimeouts 30000, 60000, 30000, 120000

Issue call webservice

Hi I am trying to communicate with a webservice in my asp.net page in my code behind (vb.net) when i make the call I get a 401 unauthorised error however when i try the same call though a simple html page it works.
here is my simple html page
<form method="post" action="https://mycallingwebpage.co.uk/login">
<input type="submit">
</form>
this works fine and returns what i would expect.
however in my vb.net code this doesn't work.
Public Function mylogin(ByVal ServiceProfile) As String
Dim xmldoc As New Xml.XmlDocument
Try
myWebClient = New WebClient
myWebClient.Headers.Add("Content-Type", "text/plain")
Dim bytRetData As Byte() = myWebClient.DownloadData("https://mycallingwebpage.co.uk/login" & ServiceProfile)
Catch ex As Exception
End Try
End Function
I have now made some steps forward.
Further to my earlier question above i am still not able to make the call. I have found that if i make a call to the http url it works but calling the the https url it does not - this ajax call below does work for me - so effectively what do i need to do to convert this code below into a webclient call in vb.net? - this needs to work for https
$.ajax({
type: "POST",
contentType: 'application/x-www-form-urlencoded',
dataType: "application/xml",
crossDomain: true,
data: {'login' : encodeURIComponent('user'),'password' : encodeURIComponent('password')} ,
url: "https://myURL.com",
success: doThis,
error: doThat
});
you have to "authorize" yourself before accessing the WS. You are probably missing an Authorization header. Sorry, I'm not much of a VB expert, but it should be something like this:
myWebClient.Headers.Add("Authorization", "Basic " + ADD_UR_SECRET_HERE)
BTW, don't forget to encode your secret token using a Base64 Encoder before adding it to the headers.
Hope it helped.