im trying right now parsing mutliple JSONs in VBA in Excel. With Google and SO i managed to parse Multiple JSONs in a Format like this:
{
"name": "Starker Geschmeidiger Holz-Langbogen des Feuers",
"description": "",
"type": "Weapon",
"level": 44,
"rarity": "Masterwork",
"vendor_value": 120,
"default_skin": 3942,
"game_types": [
"Activity",
"Wvw",
"Dungeon",
"Pve"
],
"flags": [
"SoulBindOnUse"
],
"restrictions": [],
"id": 28445,
"chat_link": "[&AgEdbwAA]",
"icon": "https://render.guildwars2.com/file/C6110F52DF5AFE0F00A56F9E143E9732176DDDE9/65015.png",
"details": {
"type": "LongBow",
"damage_type": "Physical",
"min_power": 385,
"max_power": 452,
"defense": 0,
"infusion_slots": [],
"infix_upgrade": {
"id": 142,
"attributes": [
{
"attribute": "Power",
"modifier": 85
},
{
"attribute": "Precision",
"modifier": 61
}
]
},
"suffix_item_id": 24547,
"secondary_suffix_item_id": ""
}
}
I do it like this:
Private Function Get_Name(id As Integer) As String
Dim httpObject As Object
Set httpObject = CreateObject("MSXML2.XMLHTTP")
sURL = "https://api.guildwars2.com/v2/items/" & id & "?lang=de"
sRequest = sURL
httpObject.Open "GET", sRequest, False
httpObject.send
sGetResult = httpObject.responseText
Dim oJSON As Object
Set oJSON = JsonConverter.ParseJson(sGetResult)
For Each sItem In oJSON
If sItem = "name" Then
Get_Name = oJSON(sItem)
End If
Next
End Function
That works fine, but i have one JSON i get from the API, that has a different Format and i dont manage to get this to work too.. It hast the following Format:
[
{
"id": 12134,
"category": 5,
"count": 204
},
{
"id": 12238,
"category": 5,
"count": 150
},
{
"id": 12147,
"category": 5,
"count": 146
},
{
"id": 12142,
"category": 5,
"count": 215
},
....
]
Thats my Try so Far:
Private Function Get_Anzahl_Im_Lager(id As Integer) As Integer
Dim httpObject As Object
Set httpObject = CreateObject("MSXML2.XMLHTTP")
sURL = "https://api.guildwars2.com/v2/account/materials?access_token=" & Tabelle2.Cells(1, 7)
sRequest = sURL
httpObject.Open "GET", sRequest, False
httpObject.send
sGetResult = httpObject.responseText
MsgBox sGetResult
Dim oJSON As Collection
Set oJSON = JsonConverter.ParseJson(sGetResult)
MsgBox oJSON
For Each sItem In oJSON
'If oJSON(sItem)("id") = id Then
' Get_Anzahl_Im_Lager = oJSON(sItem)("count")
' End If
Get_Anzahl_Im_Lager = sItem
Exit Function
Next
End Function
Problem is,according to the Debugger it parses the Array, but i just get an Empty Object back here, oJSON is empty, while sGetResult hast the JSON Data in it.
Any Solutions?
Made it.. Sometimes i should just start thinking from a new Point on :D
Private Function Get_Anzahl_Im_Lager(id As Integer) As Integer
Dim httpObject As Object
Set httpObject = CreateObject("MSXML2.XMLHTTP")
If Not IsEmpty(Tabelle2.Cells(1, 7)) Then
sURL = "https://api.guildwars2.com/v2/account/materials?access_token=" & Tabelle2.Cells(1, 7)
Else
Exit Function
End If
sRequest = sURL
httpObject.Open "GET", sRequest, False
httpObject.send
sGetResult = httpObject.responseText
Dim oJSON As Object
Set oJSON = JsonConverter.ParseJson(sGetResult)
Dim sItem, cnt&
For Each sItem In oJSON
cnt = cnt + 1
If oJSON(cnt)("id") = id Then
Get_Anzahl_Im_Lager = oJSON(cnt)("count")
Exit Function
End If
Next
End Function
The JSON objects are of two different types. One is dictionary and one is a collection. Use TypeName to determine which you are getting from the responseText and handle as required e.g.
Dim item As Long, oJSON As Object
Set oJSON = JsonConverter.ParseJson(sGetResult)
Select Case TypeName(oJSON)
Case "Collection"
For Each item In json
Debug.Print item("count")
Next
Case "Dictionary"
Debug.Print json("name")
End Select
Related
I have a JSON file which contains:
array("components") of Objects
some of objects may have sub array("components") some don't.
I need to extract the labels, keys of that array also the array("values") with all the labels, values.
HOWEVER following VBA code only work with first level of "components", do not dig into second or third levels. let me know if I am doing it right?
I have been using JsonConverter to parse JSON file and then using following code:
Dim jSon As Variant
Set jSon = JsonConverter.ParseJson(jSonText)
Dim components As Collection
Set components = jSon("components")
Set Dict = New Scripting.Dictionary
Dim component As Variant
For Each component In components
Dim Label, Key As String 'not used
Dict.Add component("label"), component("key")
On Error Resume Next
Dim Values As Collection
Set Values = component("components")
Dim Data As Scripting.Dictionary
Set Data = component("data")
On Error GoTo 0
Dim value As Variant
If Not Values Is Nothing Then
For Each value In Values
Dict.Add value("label"), value("value")
Next value
ElseIf Not Data Is Nothing Then
Set Values = Data("values")
For Each value In Values
Dict.Add value("label"), value("value")
Next value
Else
'Debug.Print " No values"
End If
Set Values = Nothing
Set Data = Nothing
Next component
OLD JSON FILE - above code is working fine on this
{
"display": "form",
"settings": {
"pdf": {
"id": "1ec0f8ee-6685-5d98-a847-26f67b67d6f0",
"src": "https://files8-a847-26f67b67d6f08-a847-26f67b67d6f0"
}
},
"components": [
{
"label": "Family Name",
"tableView": true,
"key": "familyName",
"type": "textfield",
"input": true
},
{
"label": "Amount of Money",
"mask": false,
"tableView": false,
"delimiter": false,
"requireDecimal": false,
"inputFormat": "plain",
"truncateMultipleSpaces": false,
"key": "amountOfMoney",
"type": "number",
"input": true
},
{
"label": "I hereby confirm",
"tableView": false,
"key": "iHerebyConfirm",
"type": "checkbox",
"input": true,
"defaultValue": false
},
{
"label": "Which Cities do you like",
"optionsLabelPosition": "right",
"tableView": false,
"values": [
{
"label": "New York",
"value": "newNew YorkYork",
"shortcut": ""
},
{
"label": "Munich",
"value": "Munich",
"shortcut": ""
},
{
"label": "Paris",
"value": "Paris",
"shortcut": ""
},
{
"label": "Hongkong",
"value": "Hongkong",
"shortcut": ""
},
{
"label": "Mumbai",
"value": "Mumbai",
"shortcut": ""
}
],
"key": "whichCitiesDoYouLike",
"type": "selectboxes",
"input": true,
"inputType": "checkbox"
},
{
"label": "Favorite color",
"widget": "choicesjs",
"tableView": true,
"data": {
"values": [
{
"label": "black",
"value": "black"
},
{
"label": "white",
"value": "white"
},
{
"label": "blue",
"value": "blue"
},
{
"label": "green",
"value": "green"
}
]
},
"key": "favoriteColor",
"type": "select",
"input": true
},
{
"type": "button",
"label": "Submit",
"key": "submit",
"disableOnInvalid": true,
"input": true,
"tableView": false
}
]
}
To understand it I used http://jsoneditoronline.org/ try to convey in following picture
Take note that I have swapped the dictionary entry using key as the dictionary key and label as the value as label is not unique (as far as the sample JSON shows) and will cause an error (or overwrite previous entry, depending on implementation).
Your usage of On Error Resume Next should be avoided (this applies to any scenario, unless you are using it on purpose which is rarely needed) as you are basically hiding all possible errors which can cause your code to produce unintended result. You can use Exists method in If..Else..End If statement to check if the dictionary key exist first and only perform the task if it do exist.
EDIT - Code updated to handle both old and new JSON format
Private Sub Test()
'==== Change this part according to your implementation..."
Dim jsontxt As String
jsontxt = OpenTxtFile("D:/TestJSON2.txt")
'====
Dim jSon As Scripting.Dictionary
Set jSon = JsonConverter.ParseJson(jsontxt)
'Check if first level of components exist and get the collection of components if true
If jSon.Exists("components") Then
Dim components As Collection
Set components = jSon("components")
Dim Dict As Scripting.Dictionary
Set Dict = New Scripting.Dictionary
Dim comFirst As Variant
Dim comSecond As Variant
Dim comThird As Variant
Dim columnsDict As Variant
Dim valDict As Variant
For Each comFirst In components
'extract key-label from first level component
If Not Dict.Exists(comFirst("label")) Then Dict.Add comFirst("label"), comFirst("key")
'++++ New JSON Format ++++
'==== Check if second level of "components" key exist and extract label-key if true
If comFirst.Exists("components") Then
For Each comSecond In comFirst("components")
If Not Dict.Exists(comSecond("label")) Then Dict.Add comSecond("label"), comSecond("key")
'=== Check if "columns" key exist and extract the key-label if true
If comSecond.Exists("columns") Then
For Each columnsDict In comSecond("columns")
'==== Check if third level of "components" key exist and extract key-label if true
If columnsDict.Exists("components") Then
For Each comThird In columnsDict("components")
If Not Dict.Exists(comThird("label")) Then Dict.Add comThird("label"), comThird("key")
'==== Check if "values" key exist and extract label-value if true
If comThird.Exists("values") Then
For Each valDict In comThird("values")
If Not Dict.Exists(valDict("label")) Then Dict.Add valDict("label"), valDict("value")
Next valDict
End If
'====
Next comThird
End If
'====
Next columnsDict
End If
'====
'==== Check if "values" key exist and extract the label-value if true
If comSecond.Exists("values") Then
For Each valDict In comSecond("values")
If Not Dict.Exists(valDict("label")) Then Dict.Add valDict("label"), valDict("value")
Next valDict
End If
'====
Next comSecond
End If
'++++
'++++ Old JSON format ++++
'==== Check if "data" key exist and extract the label-value if true
If comFirst.Exists("data") Then
If comFirst("data").Exists("values") Then
For Each valDict In comFirst("data")("values")
If Not Dict.Exists(valDict("label")) Then Dict.Add valDict("label"), valDict("value")
Next valDict
End If
End If
'====
'==== Check if "values" key exist and extract the label-value if true
If comFirst.Exists("values") Then
For Each valDict In comFirst("values")
If Not Dict.Exists(valDict("label")) Then Dict.Add valDict("label"), valDict("value")
Next valDict
End If
'====
'++++
Next comFirst
End If
End Sub
Try this:
https://github.com/VBA-tools/VBA-JSON
You need to import the file "JsonConverter.bas" in your project and then follow the examples in the README.md file
My JSON file looks like this:
{
"data": [
{
"id": "6003510075864",
"name": "Golf",
"audience_size": 242637550,
"path": [
"Interests",
"Sports and outdoors",
"Sports",
"Golf"
],
"description": "",
"topic": "Sports and outdoors"
},
{
"id": "6003393973731",
"name": "Persian Gulf",
"audience_size": 173453990,
"path": [
"Interests",
"Additional Interests",
"Persian Gulf"
],
"description": null,
"topic": "Hobbies and activities"
},...
As you can see, there is a nested array "path" , with an unknown length.
With this code im trying to access the section:
Dim hReq As Object, JSON As Object, item As Object, itempath As Object
(...)
For Each item In JSON("data")
ws.Cells(3 + i, 1) = item("id")
ws.Cells(3 + i, 2) = item("name")
ws.Cells(3 + i, 3) = item("audience_size")
ws.Cells(3 + i, 4) = item("description")
ws.Cells(3 + i, 5) = item("topic")
For Each itempath In item("path") ' <<< in this line I get the error Object needed..
ws.Cells(3 + i, 6) = itempath("0")
Next
i = i + 1
Next
The 2nd For each statement gives me an error .. I dont know how to handle this nested array ... thanks for any ideas ....
item("path")
...is a Collection of strings, not a collection of objects
Dim itempath 'as variant
'...
For Each itempath In item("path")
ws.Cells(3 + i, 6) = itempath
Next
'...
Basically I want to read some .JSONn files with very structured data (many arrays, items and values) and my goal is to put the items and values in an excel sheet. I have trouble getting stuck when I reach arrays data-type.
I can read the files and include some items and values using the Library VBA-JSON 2.3.1
Dim jsonObject As Object, i As Integer, FSO
Set FSO = CreateObject("Scripting.FileSystemObject")
Set JsonTS = FSO.OpenTextFile("D:\JSON\file.json", ForReading)
JsonText = JsonTS.ReadAll
JsonTS.Close
Set ws = Worksheets("Sheet1")
Set jsonObject = JsonConverter.ParseJson(JsonText)
i = 2
n = 1
For Each Item In jsonObject
ws.Cells(i, n) = jsonObject(Item)
i = i + 1: n = n + 1
Next
MsgBox ("Complete!")
Set jsonObject = Nothing
Here's my sructured JSON file:
{
"id": "2ca5da11-b311-43db-9661-afa3b833aad4",
"name": "_menuAposentacoes",
"auto": true,
"contexts": [],
"responses": [
{
"resetContexts": false,
"affectedContexts": [
{
"name": "aposentacoes_22-followup",
"parameters": {},
"lifespan": 2
}
],
"parameters": [
{
"id": "6e86b18e-77c1-4571-ad53-eba8db91d4b3",
"required": false,
"dataType": "#aposentacao",
"name": "aposentacao",
"value": "$aposentacao",
"promptMessages": [],
"noMatchPromptMessages": [],
"noInputPromptMessages": [],
"outputDialogContexts": [],
"isList": true
},
{
"id": "be28b756-32dd-40e7-99db-d7f91cc9ddb6",
"required": false,
"dataType": "#CGA",
"name": "CGA",
"value": "$CGA",
"promptMessages": [],
"noMatchPromptMessages": [],
"noInputPromptMessages": [],
"outputDialogContexts": [],
"isList": false
},
{
"id": "f52786f0-15cd-4fc4-983f-32b248ddcf3f",
"required": false,
"dataType": "#descontos",
"name": "descontos",
"value": "$descontos",
"promptMessages": [],
"noMatchPromptMessages": [],
"noInputPromptMessages": [],
"outputDialogContexts": [],
"isList": false
},
{
"id": "6e7f4c49-f35f-46fb-9db9-c24eb16f0b40",
"required": false,
"dataType": "#situacaoCGA",
"name": "situacaoCGA",
"value": "$situacaoCGA",
"promptMessages": [],
"noMatchPromptMessages": [],
"noInputPromptMessages": [],
"outputDialogContexts": [],
"isList": false
},
{
"id": "70328121-e748-4508-a287-7fc30a9cd9f6",
"required": false,
"dataType": "#penalizacao",
"name": "penalizacao",
"value": "$penalizacao",
"promptMessages": [],
"noMatchPromptMessages": [],
"noInputPromptMessages": [],
"outputDialogContexts": [],
"isList": false
}
],
"messages": [
{
"type": 0,
"lang": "pt",
"speech": "Some text."
},
{
"type": 4,
"lang": "pt",
"payload": {
"message": "Some text: ",
"ignoreTextResponse": false,
"platform": "kommunicate",
"metadata": {
"contentType": "300",
"templateId": "6",
"payload": [
{
"title": "Other text",
"message": "Other text"
},
{
"title": "Other text",
"message": "Other text"
},
{
"title": "Other text",
"message": "Other text"
},
{
"title": "Other text",
"message": "Other text"
}
]
}
}
},
{
"type": 4,
"lang": "pt",
"payload": {
"message": "Other text",
"ignoreTextResponse": false,
"platform": "kommunicate",
"metadata": {
"contentType": "300",
"templateId": "6",
"payload": [
{
"title": "Sim",
"message": "Sim"
},
{
"title": "Não",
"message": "Não"
}
]
}
}
}
],
"defaultResponsePlatforms": {},
"speech": []
}
],
"priority": 500000,
"webhookUsed": false,
"webhookForSlotFilling": false,
"fallbackIntent": false,
"events": []
}
Here's a useful routine that can help you determine how to parse the JSON data, based on information in this answer. The routine is recursive, so it will successively call itself to continue parsing the JSON input.
The current output is to the immediate window using Debug.Print, but you can modify these statements to put the results into worksheet cells according to your needs and format (which was not really specified in your question).
Notice that the level parameter is incremented by two with each JSON level. This is likely due to the format of the JSON source itself. For example, the top-level responses field has both a [ and a { to indicate internal structure. You can adjust the logic to deal with this however best suits your use case.
Option Explicit
Sub ImportJSON()
Dim fso As FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
Dim jsonFilename As String
Dim jsonFile As Object
Dim jsonText As String
jsonFilename = "D:\JSON\file.json"
Set jsonFile = fso.OpenTextFile(Filename:=jsonFilename, IOMode:=ForReading)
jsonText = jsonFile.ReadAll
jsonFile.Close
Dim json As Object
Set json = JsonConverter.ParseJson(jsonText)
OutputJSON "(top)", json, 1
End Sub
Sub OutputJSON(ByVal itemName As String, _
ByRef jsonItem As Variant, _
ByVal level As Long)
Dim item As Variant
Select Case TypeName(jsonItem)
Case "Dictionary"
For Each item In jsonItem
If IsObject(jsonItem(item)) Then
If jsonItem(item).Count = 0 Then
Debug.Print level & " " & itemName & "." & _
item & " is empty " & _
TypeName(jsonItem(item))
Else
OutputJSON itemName & "." & item, jsonItem(item), level + 1
End If
Else
Debug.Print level & " " & itemName & "." & _
item & " = " & jsonItem(item)
End If
Next item
Case "Collection"
Dim i As Long
i = 1
For Each item In jsonItem
If IsObject(item) Then
OutputJSON itemName & "[" & i & "]", item, level + 1
Else
Debug.Print level & ": " & itemName & "[" & i & "]", item
End If
i = i + 1
Next item
End Select
End Sub
So I have this nested JSON file
{
"root": [{
"STATUS_RE": {
"STATUS": {
"STATUS": {
"OWNER": "Manny",
"REQUEST_ID": "00000",
"STATE": "SUCCESS"
}
},
"RESPONSE_FORMAT": "New",
"OWNER": "Manny",
"REQUEST_ID": "00000",
"RESULT": [{
"USER": {
"BUSINESS_ID": "N",
"ID_NUMBER": "016",
"U_LANGUAGE": "F",
"B_CODE": "08302"
}
},
{
"USER_A": {
ROLE": "true",
"ACCESSING": "true"
}
}
}
}]
}
Im using this visual basic code trying to access certain part of this json file. For example I want "BUSINESS_ID" and "ID_Number" under "USER" and I also want "ROLE" under "USER_A"
This is the code I'm working with
Dim FSO As New FileSystemObject
Dim JsonTS As TextStream
Set JsonTS = FSO.OpenTextFile("example.json", ForReading)
JsonText = JsonTS.ReadAll
JsonTS.Close
Set JSON = ParseJson(JsonText)
i = 2
For Each Item In JSON
Sheets(1).Cells(i, 1).Value = Item("BUSINESS_ID")
Sheets(1).Cells(i, 2).Value = Item("ID_Number")
i = i + 1
I tried changing For Each Item In JSON to something like For Each Item In JSON("root")(STATUS_RE").... all the way to ("USER") then grab the "BUSINESS_ID" but that did not work, how would I extract the information I need.
For example:
Dim result As String
Dim JSON As Object
result = Range("A9").Value
Set JSON = JsonConverter.ParseJson(result)
Debug.Print JSON("root")(1)("STATUS_RE")("RESULT")(1)("USER")("ID_NUMBER") '>> 016
I am trying to write a Macros in excel to create a new column with these states divided into these regions. I keep getting runtime error 13
Here is the code I have so far.
Sub Region ()
Dim Pacific As Variant
Pacific = Array("WA", "OR", "ID", "CA", "NV", "AZ", "NM", "HI", "AK")
Dim Continental As Variant
Continental = Array("AR", "IA", "CO", "KS", "LA", "MS", "MT", "ND", "NE", "OK", "SD", "UT", "WY")
Dim SouthEast As Variant
SouthEast = Array("GA", "AL", "FL", "SC", "KY", "TN")
Dim Midwest As Variant
Midwest = Array("MN", "WI", "IL", "IN", "MI", "OH")
Dim NorthAtlantic As Variant
NorthAtlantic = Array("ME", "NH", "MA", "RI", "CT", "VT", "NY", "PA", "NJ", "DE", "MD", "WV", "VA", "NC")
Dim Texas As Variant
Texas = Array("TX”)
Dim state As String , result As String
score = Range("F1").Value
If state = Pacific Then
result = "PACIFIC"
ElseIf state = Continental Then
result = "Continental"
ElseIf state = SouthEast Then
result = "SouthEast"
ElseIf state = Midwest Then
result = "Midwest"
ElseIf state = NorthAtlantic Then
result = "North Atlantic"
ElseIf state = Texas Then
result = "Texas"
Else
result = "fail"
End If
Range("Z1").Value = result
End Sub
AFAIK, to search for the occurrence of a string within an array isn't a simple matter within VBA. You either have to use a loop, or possibly use WorksheetFunction.Match.
A simpler way may be to avoid arrays altogether - your code could be easily refactored to use a Select Case statement:
Sub Region ()
Dim state As String , result As String
state = Range("F1").Value
Select Case state
Case "WA", "OR", "ID", "CA", "NV", "AZ", "NM", "HI", "AK"
result = "PACIFIC"
Case "AR", "IA", "CO", "KS", "LA", "MS", "MT", "ND", "NE", "OK", "SD", "UT", "WY"
result = "Continental"
Case "GA", "AL", "FL", "SC", "KY", "TN"
result = "SouthEast"
Case "MN", "WI", "IL", "IN", "MI", "OH"
result = "Midwest"
Case "ME", "NH", "MA", "RI", "CT", "VT", "NY", "PA", "NJ", "DE", "MD", "WV", "VA", "NC"
result = "North Atlantic"
Case "TX"
result = "Texas"
Case Else
result = "fail"
End Select
Range("Z1").Value = result
End Sub
Note: You also had two code problems.
You had
score = Range("F1").Value
when I think you meant
state = Range("F1").Value
You had "TX” instead of "TX" - I'm not sure whether the ” causes a problem in your version of Excel, but it does in mine.
To extend this function so that it applies to all cells in column F, you will need to loop through each row:
Sub Region ()
Dim state As String , result As String
Dim lastRow As Long
Dim r As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, "F").End(xlUp).Row
For r = 1 to lastRow
state = .Cells(r, "F").Value
Select Case state
Case "WA", "OR", "ID", "CA", "NV", "AZ", "NM", "HI", "AK"
result = "PACIFIC"
Case "AR", "IA", "CO", "KS", "LA", "MS", "MT", "ND", "NE", "OK", "SD", "UT", "WY"
result = "Continental"
Case "GA", "AL", "FL", "SC", "KY", "TN"
result = "SouthEast"
Case "MN", "WI", "IL", "IN", "MI", "OH"
result = "Midwest"
Case "ME", "NH", "MA", "RI", "CT", "VT", "NY", "PA", "NJ", "DE", "MD", "WV", "VA", "NC"
result = "North Atlantic"
Case "TX"
result = "Texas"
Case Else
result = "fail"
End Select
.Cells(r, "Z").Value = result
Next
End With
End Sub
Em why don,t you use Access create tables as you did and then link to further logical tables you are going to create (I presume there is some practical use of the code you wrote) That is why access was created in the first place...