Excel VBA, Parsing Response from a HTTP request - json

This feels like it should be really simple but I'm a bit stuck. I want to access an API url using Excel VBA. The API gives me a very simple JSON response containing a load id which is used as a parameter in the calling of another API, the other API isn't a problem because I can get the response in either XML or CSV and parse it into Excel.
API Response:
{"loadid":"1234567890"}
All I need to extract from this response is the number "1234567890".
This is what I've tried so far:
Sub getLoadID()
Dim loadID As String
Dim loadIDUrl As String
loadIDUrl = "blah blah"
proxyServer = Worksheets("Sheet1").Range("A1").Value
Set httpReq = CreateObject("WinHttp.WinHttprequest.5.1")
httpReq.Open "GET", loadIDUrl, False
httpReq.setRequestHeader "Content-Type", "text/xml"
httpReq.setProxy 2, proxyServer, ""
httpReq.setTimeouts -1, -1, -1, -1
httpReq.send request
httpReq.ResponseText = loadID
Worksheets("Sheet1").Range("A2").Value = loadID
End Sub
I've tried to put the whole string into a cell just to make sure that Excel is able to obtain the string from the response but going forward will just be happy to store the value as a variable and not write it to the sheet.
The above code runs with no errors, I just don't get the string in cell A2...
Every time I've searched about parsing JSON using Excel VBA everyone recommends to use external libraries but I'm trying to do this at work so I can't use the external libraries.
Cheers

Related

add data to a datatable from JSON string - vb.net

I need to know how to populate datatable from JSON string in vb.net code.
the JSON string
{"success":true,"message":"","result":[{"Paper1:null,"StateId":"57ee","School":"1A","Received":"2018-07-03T08:10:05.22","TimeS":"00","STAT":"98","ScoreCard":"76"},{"Paper1:null,"StateId":"52ef","School":"1A","Received":"2018-07-03T08:10:05.22","TimeS":"00","STAT":"88","ScoreCard":"57"}]}
I need to know how to populate above string to a datatable
The above string is in a WebResponse. So is there any way to read the webresponse (here I have used a streamreader, or any other good method) and populate to a datatable?
my code which I got above string.
Dim rqst As WebRequest = WebRequest.Create(uri_variable)
Dim res_p As WebResponse
rqst.Method = "GET"
rqst.Headers.Add("apisign:" & sign)
res_p = rqst.GetResponse()
Dim reader As New StreamReader(res_p.GetResponseStream())
Dim JSON_String as string = reader
P.S: EDIT: I included a screenshot for the user "CruleD"
https://i.stack.imgur.com/EYbP0.png
Heh, this again.
Imports System.Web.Script.Serialization ' for reading of JSON (+add the reference to System.Web.Extensions library)
Dim JSONC = New JavaScriptSerializer().DeserializeObject(JSON_String)
Inspect JSONC with breakpoint. You will see how it looks then you decide what you want to do with it.
Comparing files not working as intended
Similar answer I gave in another thread.
Edit:
JSONC("result")(0)("Quantity")
First you get the contents of "result", then you select which collection you want, in this case first (so 0) then you search for whatever key you want again eg "Quantity" like you did for result originally.
There are other ways to do the same thing, but this one should be pretty straight forward.
There are 3 types of deserialization, check them out if you want.

JsonConverter Excel VBA multiple results

A small question: i'm using JsonConverter from Github.
(https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas)
Code is working on most of the "GET" request.
Only when the same 'column' is accuring multiple times in the 'ResponseText' then it's not. (like "imei" in the example)
So I need a way to handle a long 'Responsetext' to fill multiple rows in an access db.
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
MsgBox (Json("imei")) 'temp
Error 5: Invalid Procedure or Call Argument.
Any ideas?
Many thanks,
I can only provide a part of the answer, because I cannot recreate it, without the full JSON Response Text:
The response with mutliple values in JSON returns an Object of the type Collection. Hence you have to use a loop to iterate through all responses. Like this:
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each singleJsonItem In Json
'What object type is singleJsonItem? To find out, maybe use:
'MsgBox singleJsonItem("imei")
Next singleJsonItem
You have to find out the object type of the collectionentries to extract the JSON Entry.
Solved like this:
used : https://github.com/VBA-tools/VBA-JSON
and named the module: 'mdl_JsonConverter'
Set Json = mdl_JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each item In Json
input_1 = item("input_1")
input_2 = item("input_2")
'THEN DO SOMETHING WITH VALUES F.E. ADDING THEM IN A TABLE
Next
If you responseText contains a searchRecords list then filter by searchRecords before for each
Set Json = JsonConverter.ParseJson(strResponse)
For Each singleJsonItem In Json("searchRecords")
'What object type is singleJsonItem? To find out, maybe use:
Msgbox singleJsonItem("Name")
Next singleJsonItem

Extracting values by parsing JSON with Classic ASP

I am using Classic ASP and ASPJSON (http://www.aspjson.com/) to try to extract data returned in JSON format when sending an email via the SendGrid API.
This is some sample JSON data:
{
"message":"error",
"errors":[
"some errors"
]
}
I can access the values of the "message" section via:
Set oJSON = New aspJSON
oJSON.loadJSON(string_containing_json)
json_status = ap(oJSON.data("message"))
response.write(json_status)
However, I can't access the values of the "errors" section as it's sort of one level down.
Is it possible to get at that?
The errors are stored as a Dictionary object. You can enumerate them like this:
dim errors : set errors = oJSON.data("errors")
dim curError
for curError = 0 to errors.Count -1
Response.Write( errors(curError))
Response.Write( "<br />")
next

$.getJSON doesn't read my .aspx return

So I searched through most of the getJSON questions and am still unable to find a solution to my problem. My main problem is this: I have a .js file that makes a $.getJSON call to an .aspx page. The .aspx page returns a json object. I've tested the $.getJSON with a demo.js and it works just fine; I'm able to reference the json field. This is not the case with the .aspx page. Here is my code:
.js making the $getJSON call
$.getJSON('updateSlides.aspx', function (json) {
alert("JSON Data: " + json.url);
});
.aspx returning json obj
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim jsonString As String
If Not Page.IsPostBack Then
Dim ws As New wallboardSettings
' pull data values from db here, replace hardcoded values below
ws.duration = 5
ws.imagePath = "Images\slide1.jpg"
ws.url = "slide1.html"
Dim js As JavaScriptSerializer = New JavaScriptSerializer()
jsonString = js.Serialize(ws)
Response.Write(jsonString)
End If
End Sub
I've placed a msgbox in the VB and ran it from my local machine to see my values. It returns the ws property settings in json form, which validated correctly on jsonlint.com.
I've also tried just using an $.ajax call with async: false but it doesn't work. When I use the demo.js, which works, i see the json fields in firebug; this is not the case with the updateSlides.aspx.
Thanks in advance,
Brian
Set the content type headers to application/json from your response.
So it turns out the json wasn't the issue. the aspx page was return json just fine. According to firebug the same aspx page was also returning addition html that was autogenerated. I deleted this html and firebug showed the json data. Thanks for your reponses!

JSON import to Excel

Is it possible to script JSON calls in a macro?
I want to get a JSON string through an API connection. It looks like the problem is Excel expects the parameters to be passed in the HTML-string, but JSON passes parameters in the HTML body. Any ideas?
Since this is VBA, I'd use COM to call xmlhttprequest but use it in synchronous manner as not to upset VBA’s single threaded execution environment, A sample class that illustrates a post and get request in this manner follows:
'BEGIN CLASS syncWebRequest
Private Const REQUEST_COMPLETE = 4
Private m_xmlhttp As Object
Private m_response As String
Private Sub Class_Initialize()
Set m_xmlhttp = CreateObject("Microsoft.XMLHTTP")
End Sub
Private Sub Class_Terminate()
Set m_xmlhttp = Nothing
End Sub
Property Get Response() As String
Response = m_response
End Property
Property Get Status() As Long
Status = m_xmlhttp.Status
End Property
Public Sub AjaxPost(Url As String, Optional postData As String = "")
m_xmlhttp.Open "POST", Url, False
m_xmlhttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
m_xmlhttp.setRequestHeader "Content-length", Len(postData)
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send (postData)
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
Public Sub AjaxGet(Url As String)
m_xmlhttp.Open "GET", Url, False
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
'END CLASS syncWebRequest
So now you can call the above to return you the server's response:
Dim request As New syncWebRequest
request.ajaxGet "http://localhost/ClientDB/AllClients?format=json"
Dim json as string
json = request.Response
The problem here is we want to be able to read the data returned from the server in some way, more so than manipulating the JSON string directly. What's worked for me is using the VBA-JSON (google code export here) COM type Collection to handle JSON arrays and Dictionary to handle members and their declarations, with a parser factory method Parse that basically makes creating these collections of dictionaries much simpler.
So now we can parse the JSON:
[{"Name":"test name","Surname":"test surname","Address":{"Street":"test street","Suburb":"test suburb","City":"test city"}}]
into something like the following:
Set clients = parser.parse(request.Response)
For Each client In clients
name = client("Name")
surname = client("Surname")
street = client("Address")("Street")
suburb = client("Address")("Suburb")
city = client("Address")("City")
Next
That's nice but what about stuff like being able to edit and post back the data? Well there's also a method toString to create a JSON string from the above [Collection/Dictionary] JSON data, assuming the server accepts JSON back.
I wrote a .NET Excel-Addin for this. It's a generic Excel JSON client that streams any JSON object straight into Excel via http.
Docs and installation instructions can be found here:
http://excel-requests.pathio.com/en/master/
And here's the GitHub link:
https://github.com/ZoomerAnalytics/excel-requests