Get value of node in MS Access using JSOn - json

I am using VB-JSON parser to get data from an API and saving the data in MS access table.
I am not able to figure out how to access the -KLj9kXnKd-9txfyIqM8 and -KLjJoT7gXCMq_jHx2_z.
I have Table structure as below, and want to save the data as shown below.
|ServerID |Name |Mobile
|-KLj9kXnKd-9txfyIqM8 |Adarsh |9987
|-KLjJoT7gXCMq_jHx2_z |Manas |022
JSON
{
"-KLj9kXnKd-9txfyIqM8": {
"personmobile": "9987",
"personname": "Adarsh"
},
"-KLjJoT7gXCMq_jHx2_z": {
"personmobile": "022",
"personname": "Manas"
}
}
VBA
Public Sub GetPerson()
'I have code here which gets the json as above from api.
Dim egTran As String
If reader.Status = 200 Then
Set db = CurrentDb
Set rs = db.OpenRecordset("tblPerson", dbOpenDynaset, dbSeeChanges)
egTran = "[" & reader.responseText & "]"
Set coll = Json.parse(egTran)
For Each contact In coll
rs.AddNew
rs!Name = contact.Item("personname")
rs!Mobile = contact.Item("personmobile")
rs!ServerID = contact.Item("??????")
what do I write in ??????
rs.Update
Next
End If
End Sub
I am also open to using any other parser. The API is based on Firebase Database

I'm not familiar with VB-JSON, but obviously "??????" is not an item of contact.
Thus, if I run this test function:
Public Sub TestJsonText()
Dim DataCollection As Collection
Dim ResponseText As String
ResponseText = _
"{" & _
" ""-KLj9kXnKd-9txfyIqM8"": {" & _
" ""personmobile"": ""9987""," & _
" ""personname"": ""Adarsh""" & _
" }," & _
" ""-KLjJoT7gXCMq_jHx2_z"": {" & _
" ""personmobile"": ""022""," & _
" ""personname"": ""Manas""" & _
" }" & _
"}"
If ResponseText <> "" Then
Set DataCollection = CollectJson(ResponseText)
MsgBox "Retrieved" & Str(DataCollection.Count) & " root member(s)", vbInformation + vbOKOnly, "Web Service Success"
End If
Call ListFieldNames(DataCollection)
Set DataCollection = Nothing
End Sub
using the Json modules from VBA.CVRAPI it will print:
root
-KLj9kXnKd-9txfy
personmobile 9987
personname Adarsh
-KLjJoT7gXCMq_jH
personmobile 022
personname Manas
From the function ListFieldNames you can pick MemberName for the field name and DataCollection(Index)(CollectionItem.Data) for the field value to add records.

Related

Access Form - Current Records Count

I created a public function, so that I could call it on Access forms, and display the result in a textbox control. This is the public function:
Public Function CurrRecs(xRecName As String, frmName As Form, tblCount As String)
If Forms(frmName).NewRecord Then
frmName.txtCurrRec = "New " & xRecName & " Record"
Else
frmName.txtCurrRec = CStr(frmName.CurrentRecord) & " of " & _
DCount("ID", tblCount) & " " & xRecName & "s"
End If
End Function
This is what I have on the Form_Current()
CurrRecs("RecordType", "frmCurrentForm", "tblGetCountFromHere")
I get a compile error: Expected:=
Anyone know what I'm doing wrong?
The error is because you're declaring frmName as a form, but using it as a string in one place, and a form in another
Also, if you want the table count, use Form.RecordSet.RecordCount, not an elaborate DCount
Rewritten:
Public Function CurrRecs(xRecName As String, frmName As String)
Dim frm As Form
Set frm = Forms(frmName)
If frm NewRecord Then
frm.txtCurrRec = "New " & xRecName & " Record"
Else
frm.txtCurrRec = CStr(frm.CurrentRecord) & " of " & _
frm.RecordSet.RecordCount & " " & xRecName & "s"
End If
End Function

Output ADODB.RecordSet as JSON

I'm trying to change my application so that it outputs JSON instead of HTML when it makes an AJAX request for some data. I have an ADODB RecordSet. I need to loop through it row-by-row and add/change/remove different values. Then I need to take all the modified rows and response.write them as JSON. I'm using JSON2.asp so my application already supports JSON.parse & JSON.stringify but I can't get it to spit out the multi-dimensional array as JSON.
set rs = conn.execute(strQuery)
if Not rs.EOF Then
rsArray = rs.GetRows() 'This pulls in all the results of the RecordSet as a 2-dimensional array
columnCount = ubound(rsArray,1)
rowCount = ubound(rsArray,2)
For rowIndex = 0 to rowCount 'Loop through rows as the outer loop
rsArray(3,0) = "somethingelse"
Next 'Move on to next row if there is one
response.write JSON.stringify(rsArray) & " _______ "
End If
I just need to be able to go through the results of my database query, modify the results, and then output the modified results in JSON format. What's the right way to do this?
The JSON2.asp implementation doesn't have a "Load From Database" function which means you will have to implement something to convert the ADODB.Recordset to a JSON structure yourself.
If you are willing to use a different script there is an implementation by RCDMK on GitHub that does have a LoadRecordset() method, it's called JSON object class 3.5.3.
This makes loading data from an ADODB.Recordset really straightforward.
<!-- #include virtual="/jsonObject.class.asp" -->
<%
Response.LCID = 2057
'...
Dim rs: Set rs = conn.execute(strQuery)
Dim JSON: Set JSON = New JSONobject
Call JSON.LoadRecordset(rs)
Call Response.Clear()
Response.ContentType = "application/json"
Call JSON.Write()
%>
Code has been tested using a disconnected recordset, the ... here denote assumed code to setup your recordset, connection etc
It's worth noting you could write this yourself, it's not a huge leap to loop through an ADODB.Recordset and build a JSON string. However, I would argue against for a few reasons;
It is a time-consuming exercise.
Very easy to miss something (like checking for numeric data types, when generating output).
Depending on how it is coded can make it awkward to maintain (For example, if not injecting property names directly from the recordset and choosing to "hardcode" them instead).
Why reinvent the wheel ? There are a lot of public implementations in the wild that deal with the issues raised here. Admittedly, some are better than others, but it takes five minutes to include them and give it a try.
Just for completeness here is my local test code using a disconnected recordset
<!-- #include virtual="/jsonObject.class.asp" -->
<%
Call init()
Sub init()
Dim fields: fields = Array(Array("title", adVarChar, 50), Array("firstname", adVarChar, 50), Array("lastname", adVarChar, 50), Array("age", adInteger, 4))
Dim rs: Set rs = Server.CreateObject("ADODB.Recordset")
Call InsertRow(rs, fields, Array("Mr", "Joe", "Bloggs", 31))
Call InsertRow(rs, fields, Array("Mr", "John", "Smith", 42))
Response.LCID = 2057
Dim JSON: Set JSON = New JSONobject
Call JSON.LoadRecordset(rs)
Call Response.Clear()
Response.ContentType = "application/json"
Call JSON.Write()
End Sub
Sub InsertRow(ByVal rs, fields, values)
With rs
If rs.State <> adStateOpen Then
For Each fld In fields
Call .Fields.Append(fld(0), fld(1), fld(2))
Next
.CursorLocation = adUseClient
.CursorType = adOpenDynamic
Call .Open()
End If
Call .AddNew()
For i = 0 To UBound(fields, 1)
.Fields(fields(i)(0)).Value = values(i)
Next
Call .Update()
Call .MoveFirst()
End With
End Sub
%>
Output:
{"data":[{"title":"Mr","firstname":"Joe","lastname":"Bloggs","age":31},{"title":"Mr","firstname":"John","lastname":"Smith","age":42}]}
Here ya go. This works for me.
set rs = conn.execute(strQuery)
c=0
Response.write "["
Do Until rs.eof
'Assign variables here with whatever you need to change
title = rs(0)
fName = rs(1)
lName = rs(2)
empID = rs(3)
With Response
if c > 0 then .write ", "
.write "{" & chr(34) & "Title" & chr(34) & " : " & chr(34) & title & chr(34) & ", " & chr(34) & "FirstName" & chr(34) & " : " & chr(34) & fName & chr(34) & ", "
.write chr(34) & "LastName" & chr(34) & " : " & chr(34) & lName & chr(34) & ", " & chr(34) & "EmpID" & chr(34) & " : " & chr(34) & empID & chr(34) & "}"
End With
c = c + 1
rs.MoveNext
Loop
Response.write "]"
This will write your JSON object directly to the page.
try setting content-type to "application/json" on top of your asp page.
<%#LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%
Option Explicit
Response.Buffer=True
Response.ContentType="application/json"
Response.Charset="utf-8"
'' rest of your code.. your db operations
'' response write your json
%>

Trouble parsing JSON with vba

I can get what appears to be a valid JSON string from a web query, however, I cannot set items correctly for the life of me. Need to confirm that I'm not losing my mind...
'Call for available reports
Dim URLReporta As String
Dim JSONa As Object
Dim var As Object
Set myrequesta = CreateObject("winhttp.winhttprequest.5.1")
URLReporta = ("https://secure.saashr.com:443/ta/rest/v1/reports?type=Saved&company%3shortname=" & Company)
myrequesta.Open "GET", URLReporta, False
myrequesta.setRequestHeader "Accept", "application/json"
myrequesta.setRequestHeader "Authentication", "Bearer " & Token
myrequesta.setRequestHeader "Content-Type", "application/json"
myrequesta.Send
Set JSONa = JsonConverter.ParseJson(myrequesta.responseText)
Set var = JSONa("SavedName")
Debug.Print var.Count
I get an error on the line Set var = JSONa("SavedName"):
run-time error '424': object required
myrequesta.responseText value is as follows:
{"reports":[{"SavedName":"This Year","SettingId":18959322},{"SavedName":"Time Off Requests","SettingId":18960210},{"SavedName":"Calc Hours Summary","SettingId":18960209},{"SavedName":"roster","SettingId":18960211},{"SavedName":"E/D/T","SettingId":18823042},{"SavedName":"TestZDR","SettingId":18957188}]}
The structure returned by JsonConverter.ParseJson function doesn't work such way. For your particular JSON it contains 3 levels:
Root-level object has only one property reports, which contains second-level array, which in turn contains 6 third-level objects, having properties SavedName and SettingId. You are trying to get third-level's object property value from root-level object.
First you need to get second-level array, then loop through it's elements, containing objects, and retrieve the SavedName properties' values of that objects. Here is the example:
'Call for available reports
Dim URLReporta As String
Dim JSONa As Object
Dim var As Object
Dim rep As Variant
Set myrequesta = CreateObject("winhttp.winhttprequest.5.1")
URLReporta = ("https://secure.saashr.com:443/ta/rest/v1/reports?type=Saved&company%3shortname=" & Company)
myrequesta.Open "GET", URLReporta, False
myrequesta.setRequestHeader "Accept", "application/json"
myrequesta.setRequestHeader "Authentication", "Bearer " & Token
myrequesta.setRequestHeader "Content-Type", "application/json"
myrequesta.Send
Set JSONa = JsonConverter.ParseJson(myrequesta.responseText) ' root level object
Set var = JSONa("reports") ' second level array
For Each rep In var ' third level objects
Debug.Print rep("SavedName") ' property "SavedName" value of current third level object
Next
Here is the output:
If you want just to get the number of reports, then get the array and the number of elements in it:
Debug.Print JSONa("reports").Count
JSON objects can be thought of as a collection of dictionaries. So you have to walk through the inner values such as SavedName to retrieve whole dictionary objects (all SavedName values) or specific string values at indexed locations (one SavedName value):
Public Sub GetJSONRequest()
Dim jsonStr As String
jsonStr = "{" _
& " ""reports"": [{" _
& " ""SavedName"": ""This Year""," _
& " ""SettingId"": 18959322" _
& " }, {" _
& " ""SavedName"": ""Time Off Requests""," _
& " ""SettingId"": 18960210" _
& " }, {" _
& " ""SavedName"": ""Calc Hours Summary""," _
& " ""SettingId"": 18960209" _
& " }, {" _
& " ""SavedName"": ""roster""," _
& " ""SettingId"": 18960211" _
& " }, {" _
& " ""SavedName"": ""E/D/T""," _
& " ""SettingId"": 18823042" _
& " }, {" _
& " ""SavedName"": ""TestZDR""," _
& " ""SettingId"": 18957188" _
& " }]" _
& " }"
Dim JSONa As Object, element As Object, e As Variant, i As Variant, var As Variant
Set JSONa = ParseJson(jsonStr)
' DICTIONARY OBJECT
Set element = CreateObject("Scripting.Dictionary")
Set element = JSONa("reports")
' OUTER DICTIONARY
For Each e In element
' INNER COLLECTION OF DICTIONARIES
For Each i In e
Debug.Print i & " " & e(i)
Next i
Next e
' STRING VALUE OF FIRST SAVEDNAME VALUE
var = JSONa("reports")(1)("SavedName")
Debug.Print var
Set element = Nothing
Set JSONa = Nothing
End Sub
Output
SavedName This Year
SettingId 18959322
SavedName Time Off Requests
SettingId 18960210
SavedName Calc Hours Summary
SettingId 18960209
SavedName roster
SettingId 18960211
SavedName E/D/T
SettingId 18823042
SavedName TestZDR
SettingId 18957188
This Year

Parsing JSON (US BLS) in VBA from MS Access

Thank you in advance for your assistance.
I am using a JSON VB6 Parser which can be found at: VB JSON Parser
I have the following JSON response (Comes from the BLS website, specifically this link Here:
{"status":"REQUEST_SUCCEEDED","responseTime":71,"message":[],"Results":{
"series":
[{"seriesID":"WPS012","data":[{"year":"2014","period":"M11","periodName":"November","value":"153.6","footnotes":[{"code":"P","text":"Preliminary. All indexes are subject to revision four months after original publication."}]},{"year":"2014","period":"M10","periodName":"October","value":"147.4","footnotes":[{"code":"P","text":"Preliminary. All indexes are subject to revision four months after original publication."}]},{"year":"2014","period":"M09","periodName":"September","value":"146.5","footnotes":[{"code":"P","text":"Preliminary. All indexes are subject to revision four months after original publication."}]},{"year":"2014","period":"M08","periodName":"August","value":"156.9","footnotes":[{"code":"P","text":"Preliminary. All indexes are subject to revision four months after original publication."}]},{"year":"2014","period":"M07","periodName":"July","value":"156.4","footnotes":[{}]},{"year":"2014","period":"M06","periodName":"June","value":"179.6","footnotes":[{}]},{"year":"2014","period":"M05","periodName":
"May","value":"205.4","footnotes":[{}]},{"year":"2014","period":"M04","periodName":"April","value":"201.6","footnotes":[{}]},{"year":"2014","period":"M03","periodName":"March","value":"188.1","footnotes":[{}]},{"year":"2014","period":"M02","periodName":"February","value":"180.2","footnotes":[{}]},{"year":"2014","period":"M01","periodName":"January","value":"177.8","footnotes":[{}]},{"year":"2013","period":"M12","periodName":"December","value":"183.2","footnotes":[{}]},{"year":"2013","period":"M11","periodName":"November","value":"180.4","footnotes":[{}]},{"year":"2013","period":"M10","periodName":"October","value":"186.4","footnotes":[{}]},{"year":"2013","period":"M09","periodName":"September","value":"197.1","footnotes":[{}]},{"year":"2013","period":"M08","periodName":"August","value":"222.2","footnotes":[{}]},{"year":"2013","period":"M07","periodName":"July","value":"252.9","footnotes":[{}]},{"year":"2013","period":"M06","periodName":"June","value":"259.0","footnotes":[{}]},{"year":"2013","period":"M05","p
eriodName":"May","value":"263.7","footnotes":[{}]},{"year":"2013","period":"M04","periodName":"April","value":"249.3","footnotes":[{}]},{"year":"2013","period":"M03","periodName":"March","value":"268.1","footnotes":[{}]},{"year":"2013","period":"M02","periodName":"February","value":"267.1","footnotes":[{}]},{"year":"2013","period":"M01","periodName":"January","value":"279.7","footnotes":[{}]},{"year":"2012","period":"M12","periodName":"December","value":"283.2","footnotes":[{}]},{"year":"2012","period":"M11","periodName":"November","value":"280.8","footnotes":[{}]},{"year":"2012","period":"M10","periodName":"October","value":"286.7","footnotes":[{}]},{"year":"2012","period":"M09","periodName":"September","value":"285.2","footnotes":[{}]},{"year":"2012","period":"M08","periodName":"August","value":"298.9","footnotes":[{}]},{"year":"2012","period":"M07","periodName":"July","value":"275.8","footnotes":[{}]},{"year":"2012","period":"M06","periodName":"June","value":"226.9","footnotes":[{}]},{"year":"2012","perio
d":"M05","periodName":"May","value":"233.7","footnotes":[{}]},{"year":"2012","period":"M04","periodName":"April","value":"239.9","footnotes":[{}]},{"year":"2012","period":"M03","periodName":"March","value":"243.6","footnotes":[{}]},{"year":"2012","period":"M02","periodName":"February","value":"239.9","footnotes":[{}]},{"year":"2012","period":"M01","periodName":"January","value":"243.8","footnotes":[{}]}]}]
}}`
I am able to use the parser to return "status", "responseTime" and "message". Anything beyond that (the opening of the second curly bracket) I get nothing.
Below is the code I am trying to use:
Dim p As Object
Set p = JSON.parse(gbl_response)
'Print the text of a nested property '
Debug.Print p.Item("responseTime")
'Print the text of a property within an array '
Debug.Print p.Item("Results").Item("series").Item("seriesID")
The print of p.Item("responseTime") works and returns "71", however I get an "invalid call procedure or argument" error on the second print attempt.
For the life of me, I've searched around and have not found any solutions. I've tried this which seemed almost identical, but alas, I've tried to replicate the solution here and it seems to have not worked.
Thank you for you assistance!
Public Const jsonSource As String = "{" & _
"""status"": ""REQUEST_SUCCEEDED"", " & _
"""responseTime"": 71, " & _
"""message"": [ " & _
"], " & _
"""Results"": { " & _
"""series"": [ " & _
"{ " & _
"""seriesID"": ""WPS012"", " & _
"""data"": [ " & _
"{ " & _
"""year"": ""2014"", " & _
"""period"": ""M11"", " & _
"""periodName"": ""November"", " & _
"""value"": ""153.6"", " & _
"""footnotes"": [ " & _
"{ " & _
"""code"": ""P"", " & _
"""text"": ""Preliminary. All indexes are subject to revision four months after original publication."" " & _
"} " & _
"] " & _
"} " & _
"] " & _
"}]}}"
Sub JsonTest()
Dim jsonData As Scripting.Dictionary
Set jsonData = JSON.parse(jsonSource)
Dim responseTime As String
responseTime = jsonData("responseTime")
Dim results As Scripting.Dictionary
Set results = jsonData("Results")
Dim series As Collection
Set series = results("series")
Dim seriesItem As Scripting.Dictionary
For Each seriesItem In series
Dim seriesId As String
seriesId = seriesItem("seriesID")
Debug.Print seriesId
Dim data As Collection
Set data = seriesItem("data")
Dim dataItem As Scripting.Dictionary
For Each dataItem In data
Dim year As String
year = dataItem("year")
Dim period As String
period = dataItem("period")
Dim periodName As String
periodName = dataItem("periodName")
Dim value As String
value = dataItem("value")
Dim footnotes As Collection
Set footnotes = dataItem("footnotes")
Dim footnotesItem As Scripting.Dictionary
For Each footnotesItem In footnotes
Dim code As String
code = footnotesItem("code")
Dim text As String
text = footnotesItem("text")
Next footnotesItem
Next dataItem
Next seriesItem
End Sub

Cascading Combobox

Copy from: https://softwareengineering.stackexchange.com/questions/158330/cascading-comboboxes
ok so i have a form, in Access 2010, with 1 Textbox and 3 ComboBoxes (1 Enabled & 2 Disabled).
the first ComboBox is not tied to the datasource but is subjective to the other 2 comboboxes. So i handled the Click event for the first Combobox to then make the other 2 enabled, and preload the 2nd ComboBox with a custom RowSource SQL Script dynamically built based on the 1st ComboBox Value.
This all works great for New information but when i goto review the information, via Form, its back to the New mode on the controls.
Question:
What event do i need to handle to check if the current Form Data contains data for the Control Source of the Controls?
As i would express it in Logic (its a mix between C & VB, i know but should get the pt acrossed):
DataSet ds = Form.RowSet
if (ds = Null) then
cbo2.enabled = false
cbo3.enabled = false
else
cbo2.rowsource = "select id, nm from table"
cbo2.value = ds(3)
cbo3.value = ds(4)
end if
... do some other logic ...
Updated Logic - Still problem, cant catch for RecordStatus for some reason (gives 3251 Run-Time Error)
Private Sub Form_Current()
Dim boolnm As Boolean: boolnm = (IsNull(txtName.Value) Or IsEmpty(txtName.Value))
Dim booltype As Boolean: booltype = IsNull(cboType.Value)
Dim boolfamily As Boolean: boolfamily = IsNull(cboType.Value)
Dim boolsize As Boolean: boolsize = IsNull(cboType.Value)
Dim rs As DAO.Recordset: Set rs = Me.Recordset
MsgBox rs.AbsolutePosition
' If rs.RecordStatus = dbRecordNew Then
' MsgBox "New Record being inserted, but not committed yet!", vbOKOnly
' Else
' MsgBox rs(0).Name & " - " & rs(0).Value & vbCrLf & _
' rs(1).Name & " - " & rs(1).Value & vbCrLf & _
' rs(2).Name & " - " & rs(2).Value & vbCrLf & _
' rs(3).Name & " - " & rs(3).Value
' End If
'MsgBox "Name: " & CStr(boolnm) & vbCrLf & _
"Type: " & CStr(booltype) & vbCrLf & _
"Family: " & CStr(boolfamily) & vbCrLf & _
"Size: " & CStr(boolsize), vbOKOnly
End Sub
Here is the final result, with Remou's assistance, and this is only a precursor to the end result (which is out of the context of the question).
Private Sub Form_Current()
If Me.NewRecord Then <=======================
cboType.Value = 0
cboType.Enabled = True
cboFamily.Enabled = False
cboSize.Enabled = False
Else
Dim rs As DAO.Recordset: Set rs = Me.Recordset
'get Family ID
Dim fid As String: fid = rs(2).Value
'Build SQL Query to obtain Type ID
Dim sql As String
sql = "select tid from tblFamily where id = " & fid
'Create Recordset
Dim frs As DAO.Recordset
'Load SQL Script and Execute to obtain Type ID
Set frs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbReadOnly)
'Set Type ComboBox Value to Type ID
cboType.Value = frs(0)
cboType_Click 'Simulate Click Event since the Value has changed
'Make sure all 3 Comboboxes are enabled and useable
cboType.Enabled = True
End If
End Sub