Excel macros Help. Creating a new column based of arrays. - arrays

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...

Related

how do you access every value inside the hashes within an array in json type of file?

I want to access every value of strIngredient1 key. I am not good yet at coding, but my guess is that I would have to use looping to get it, but don't really know the way to formulate it.
JSON file:
{"drinks":[{"strIngredient1":"Light rum"},{"strIngredient1":"Applejack"},{"strIngredient1":"Gin"},{"strIngredient1":"Dark rum"},{"strIngredient1":"Sweet Vermouth"},{"strIngredient1":"Strawberry schnapps"},{"strIngredient1":"Scotch"},{"strIngredient1":"Apricot brandy"},{"strIngredient1":"Triple sec"},{"strIngredient1":"Southern Comfort"},{"strIngredient1":"Orange bitters"},{"strIngredient1":"Brandy"},{"strIngredient1":"Lemon vodka"},{"strIngredient1":"Blended whiskey"},{"strIngredient1":"Dry Vermouth"},{"strIngredient1":"Amaretto"},{"strIngredient1":"Tea"},{"strIngredient1":"Champagne"},{"strIngredient1":"Coffee liqueur"},{"strIngredient1":"Bourbon"},{"strIngredient1":"Tequila"},{"strIngredient1":"Vodka"},{"strIngredient1":"A\u00f1ejo rum"},{"strIngredient1":"Bitters"},{"strIngredient1":"Sugar"},{"strIngredient1":"Kahlua"},{"strIngredient1":"demerara Sugar"},{"strIngredient1":"Dubonnet Rouge"},{"strIngredient1":"Watermelon"},{"strIngredient1":"Lime juice"},{"strIngredient1":"Irish whiskey"},{"strIngredient1":"Apple brandy"},{"strIngredient1":"Carbonated water"},{"strIngredient1":"Cherry brandy"},{"strIngredient1":"Creme de Cacao"},{"strIngredient1":"Grenadine"},{"strIngredient1":"Port"},{"strIngredient1":"Coffee brandy"},{"strIngredient1":"Red wine"},{"strIngredient1":"Rum"},{"strIngredient1":"Grapefruit juice"},{"strIngredient1":"Ricard"},{"strIngredient1":"Sherry"},{"strIngredient1":"Cognac"},{"strIngredient1":"Sloe gin"},{"strIngredient1":"Apple juice"},{"strIngredient1":"Pineapple juice"},{"strIngredient1":"Lemon juice"},{"strIngredient1":"Sugar syrup"},{"strIngredient1":"Milk"},{"strIngredient1":"Strawberries"},{"strIngredient1":"Chocolate syrup"},{"strIngredient1":"Yoghurt"},{"strIngredient1":"Mango"},{"strIngredient1":"Ginger"},{"strIngredient1":"Lime"},{"strIngredient1":"Cantaloupe"},{"strIngredient1":"Berries"},{"strIngredient1":"Grapes"},{"strIngredient1":"Kiwi"},{"strIngredient1":"Tomato juice"},{"strIngredient1":"Cocoa powder"},{"strIngredient1":"Chocolate"},{"strIngredient1":"Heavy cream"},{"strIngredient1":"Galliano"},{"strIngredient1":"Peach Vodka"},{"strIngredient1":"Ouzo"},{"strIngredient1":"Coffee"},{"strIngredient1":"Spiced rum"},{"strIngredient1":"Water"},{"strIngredient1":"Espresso"},{"strIngredient1":"Angelica root"},{"strIngredient1":"Orange"},{"strIngredient1":"Cranberries"},{"strIngredient1":"Johnnie Walker"},{"strIngredient1":"Apple cider"},{"strIngredient1":"Everclear"},{"strIngredient1":"Cranberry juice"},{"strIngredient1":"Egg yolk"},{"strIngredient1":"Egg"},{"strIngredient1":"Grape juice"},{"strIngredient1":"Peach nectar"},{"strIngredient1":"Lemon"},{"strIngredient1":"Firewater"},{"strIngredient1":"Lemonade"},{"strIngredient1":"Lager"},{"strIngredient1":"Whiskey"},{"strIngredient1":"Absolut Citron"},{"strIngredient1":"Pisco"},{"strIngredient1":"Irish cream"},{"strIngredient1":"Ale"},{"strIngredient1":"Chocolate liqueur"},{"strIngredient1":"Midori melon liqueur"},{"strIngredient1":"Sambuca"},{"strIngredient1":"Cider"},{"strIngredient1":"Sprite"},{"strIngredient1":"7-Up"},{"strIngredient1":"Blackberry brandy"},{"strIngredient1":"Peppermint schnapps"},{"strIngredient1":"Creme de Cassis"}]}
You could parse the json and map the values:
data = {"drinks":[{"strIngredient1":"Light rum"},...
parsed_json = JSON.parse(data, symbolize_names: true)
strIngredient1s = parsed_json[:drinks].map { |hash| hash[:strIngredient1] }
You can do something like this:
require 'json'
def retrieve_values(json:)
drinks_result = []
JSON.parse(json, {:symbolize_names => true})[:drinks].each do |k, v|
drinks_result << v
end
end
drinks_result
The above code first parse the JSON you receive as a parameter then iterates over the list of drinks where k is the key of the sub-hashes, example: **k** -> strIngredient1 and v is the value, example: **v** -> Coffee brandy, you can use the code above as follow: retrieve_values(json: json_to_parse). The result is a list with all the values, you can iterate over that list as follow:
retrieve_values(json: json_to_parse).each do |drink_i|
...execute your code here
end
You have inserted newlines in your string for display purposes. If str is your string your actual strings is presumably
json = str.delete("\n")
Since
require 'json'
JSON.parse(json)["drinks"]
returns an array of hashes, all of which have the single key "strIngredient1", we may write
JSON.parse(json)["drinks"].map { |h| h["strIngredient1"] }
or
JSON.parse(json)["drinks"].flat_map(&:values)
Both return the array:
["Light rum", "Applejack", "Gin", "Dark rum", "Sweet Vermouth",
"Strawberry schnapps", "Scotch", "Apricot brandy", "Triple sec",
"Southern Comfort", "Orange bitters", "Brandy", "Lemon vodka",
"Blended whiskey", "Dry Vermouth", "Amaretto", "Tea", "Champagne",
"Coffee liqueur", "Bourbon", "Tequila", "Vodka", "Añejo rum", "Bitters",
"Sugar", "Kahlua", "demerara Sugar", "Dubonnet Rouge", "Watermelon",
"Lime juice", "Irish whiskey", "Apple brandy", "Carbonated water",
"Cherry brandy", "Creme de Cacao", "Grenadine", "Port", "Coffee brandy",
"Red wine", "Rum", "Grapefruit juice", "Ricard", "Sherry", "Cognac",
"Sloe gin", "Apple juice", "Pineapple juice", "Lemon juice", "Sugar syrup",
"Milk", "Strawberries", "Chocolate syrup", "Yoghurt", "Mango", "Ginger",
"Lime", "Cantaloupe", "Berries", "Grapes", "Kiwi", "Tomato juice",
"Cocoa powder", "Chocolate", "Heavy cream", "Galliano", "Peach Vodka",
"Ouzo", "Coffee", "Spiced rum", "Water", "Espresso", "Angelica root",
"Orange", "Cranberries", "Johnnie Walker", "Apple cider", "Everclear",
"Cranberry juice", "Egg yolk", "Egg", "Grape juice", "Peach nectar",
"Lemon", "Firewater", "Lemonade", "Lager", "Whiskey", "Absolut Citron",
"Pisco", "Irish cream", "Ale", "Chocolate liqueur", "Midori melon liqueur",
"Sambuca", "Cider", "Sprite", "7-Up", "Blackberry brandy",
"Peppermint schnapps", "Creme de Cassis"]

Ruby set hash inside the Hash for the Array of Hashes

I am working on Rails 6 API. This is what I get
"data": [
{
"invoice_details": {
"customer_name": "Dylan Sollfrank",
"invoice_number": "1060",
"invoice_status": "paid"
}
},
{
"transaction_number": "QB1589148496",
"customer_name": "Freeman Sporting Goods:55 Twin Lane",
"amount": {
"amount_to_pay": 86.4,
"payment_fee": 0.0
},
"created_time": "03:38 AM",
"created_date": "May 11, 2020",
"payment_method": "qb_payment",
"payment_status": "completed"
},
Following is my code
def get_payment_report_activity(invoice_transactions, timezone = Time.zone.name)
invoice_details = []
transaction_details = {}
amount = {}
invoice_transactions.group_by(&:paymentable_id).each do |key, transactions|
invoice = Invoice.find key
invoice_details.push(invoice_details:{
customer_name: invoice&.customer&.fully_qualified_name&.strip,
invoice_number: invoice&.doc_number,
invoice_status: invoice&.invoice_status
})
transactions.each do |transaction|
customer = transaction&.paymentable&.customer
amount[:amount_to_pay] = transaction&.amount_to_pay.to_f
amount[:payment_fee] = transaction&.payment_fee.to_f
transaction_details[:transaction_number] = transaction&.transaction_number
transaction_details[:customer_name] = customer&.fully_qualified_name&.strip
transaction_details[:amount] = amount
transaction_details[:created_time] = Customer.time_format(transaction.created_at.in_time_zone(timezone))
transaction_details[:created_date] = Customer.date_format(transaction.created_at.in_time_zone(timezone))
transaction_details[:payment_method] = transaction&.payment_method
transaction_details[:payment_status] = transaction&.payment_status
end
invoice_details << transaction_details
end
invoice_details
end
Now I need the hash transaction details inside the invoice_details hash label as transaction_details and there can be multiple transaction details inside the invoice_details
"data": [
{
"invoice_details": {
"customer_name": "Dylan Sollfrank",
"invoice_number": "1060",
"invoice_status": "paid",
"transaction_details: [{
"transaction_number": "QB1589148496",
"customer_name": "Freeman Sporting Goods:55 Twin Lane",
"amount": {
"amount_to_pay": 86.4,
"payment_fee": 0.0
},
"created_time": "03:38 AM",
"created_date": "May 11, 2020",
"payment_method": "qb_payment",
"payment_status": "completed"
},
{
"transaction_number": "QB1589148496",
"customer_name": "Freeman Sporting Goods:55 Twin Lane",
"amount": {
"amount_to_pay": 86.4,
"payment_fee": 0.0
},
"created_time": "03:38 AM",
"created_date": "May 11, 2020",
"payment_method": "qb_payment",
"payment_status": "completed"
}]
},
"invoice_details": {
"customer_name": "Dylan Sollfrank",
"invoice_number": "1060",
"invoice_status": "paid",
"transaction_details : {
"transaction_number": "QB1589148496",
"customer_name": "Freeman Sporting Goods:55 Twin Lane",
"amount": {
"amount_to_pay": 86.4,
"payment_fee": 0.0
},
"created_time": "03:38 AM",
"created_date": "May 11, 2020",
"payment_method": "qb_payment",
"payment_status": "completed"
}
},
}
you can try like this:
def get_payment_report_activity(invoice_transactions, timezone = Time.zone.name)
invoice_details = []
invoice_transactions.group_by(&:paymentable_id).each do |key, transactions|
invoice = Invoice.find key
transaction_details = []
transactions.each do |transaction|
transaction_hash = {}
amount_hash = {}
customer = transaction&.paymentable&.customer
amount_hash[:amount_to_pay] = transaction&.amount_to_pay.to_f
amount_hash[:payment_fee] = transaction&.payment_fee.to_f
transaction_hash[:transaction_number] = transaction&.transaction_number
transaction_hash[:customer_name] = customer&.fully_qualified_name&.strip
transaction_hash[:created_time] = Customer.time_format(transaction.created_at.in_time_zone(timezone))
transaction_hash[:created_date] = Customer.date_format(transaction.created_at.in_time_zone(timezone))
transaction_hash[:payment_method] = transaction&.payment_method
transaction_hash[:payment_status] = transaction&.payment_status
transaction_hash[:amount] = amount_hash
transaction_details << transaction_hash
end
invoice_details.push(invoice_details: {
customer_name: invoice&.customer&.fully_qualified_name&.strip,
invoice_number: invoice&.doc_number,
invoice_status: invoice&.invoice_status,
transaction_details: transaction_details
})
end
invoice_details
end

How to get all items in multiple Arrays in a JSON file using VBA?

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

Problem while parsing a specific JSON in VBA

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

Obtaining keys and values from JSON nested array in nest

First time posting! I am converting JSON data (dictionary) from a server into a csv file. The keys and values taken are fine apart from the nest "Astronauts", which is an array. Basically every individual JSON string is a datum that may contains from 0 to an unlimited number of astronauts which features I would like to extract as independent values. For instance something like this:
Astronaut1_Spaceships_First: Katabom
Astronaut1_Spaceships_Second: The Kraken
Astronaut1_name: Jebeddia
(...)
Astronaut2_gender: Hopefully female
and so on. The problem here is that the nest is set as an array and not a dictionary so I do not know what to do. I have tried the dpath library as well as flattering the nest but nothing did change. Any ideas?
import json
import os
import csv
import datetime
import dpath.util #Dpath library needs to be installed first
datum = {"Mission": "Make Earth Greater Again", "Objective": "Prove Earth is flat", "Astronauts": [{"Spaceships": {"First": "Katabom", "Second": "The Kraken"}, "Name": "Jebeddiah", "Gender": "Hopefully male", "Age": 35, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}, {"Spaceships": {"First": "The Kraken", "Second": "Minnus I"}, "Name": "Bob", "Gender": "Hopefully female", "Age": 23, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}]}
#Parsing process
parsed = json.loads(datum) #datum is the JSON string retrieved from the server
def flattenjson(parsed, delim):
val = {}
for i in parsed.keys():
if isinstance(parsed[i], dict):
get = flattenjson(parsed[i], delim)
for j in get.keys():
val[i + delim + j] = get[j]
else:
val[i] = parsed[i]
return val
flattened = flattenjson(parsed,"__")
#process of creating csv file
keys=['Astronaut1_Spaceship_First','Astronaut2_Spaceship_Second', 'Astronaut1_Name] #reduced to 3 keys for this example
writer = csv.DictWriter(OD, keys ,restval='Null', delimiter=",", quotechar="\"", quoting=csv.QUOTE_ALL, dialect= "excel")
writer.writerow(flattened)
.
#JSON DATA FROM SERVER
{
"Mission": "Make Earth Greater Again",
"Objective": "Prove Earth is flat",
"Astronauts": [ {
"Spaceships": {
"First": "Katabom",
"Second": "The Kraken"
},
"Name": "Jebeddiah",
"Gender": "Hopefully male",
"Age": 35,
"Prefered colleages": [],
"Following missions": [
{
"Payment_status": "TO BE CONFIRMED"
}
]
},
{
"Spaceships": {
"First": "The Kraken",
"Second": "Minnus I"
},
"Name": "Bob",
"Gender": "Hopefully female",
"Age": 23,
"Prefered colleages": [],
"Following missions": [
{
"Payment_status": "TO BE CONFIRMED"
}
]
},
]
}
]
Firstly, the datum you have defined here is not the datum that would be extracted from the server. The datum from the server would be a string. The datum you have in this program is already processed. Now, assuming datum to be:
datum = '{"Mission": "Make Earth Greater Again", "Objective": "Prove Earth is flat", "Astronauts": [{"Spaceships": {"First": "Katabom", "Second": "The Kraken"}, "Name": "Jebeddiah", "Gender": "Hopefully male", "Age": 35, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}, {"Spaceships": {"First": "The Kraken", "Second": "Minnus I"}, "Name": "Bob", "Gender": "Hopefully female", "Age": 23, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}]}'
You don't need the the dpath library. The problem here is that your json flattener doesn't handle embedded lists. Try using the one I've put below.
Assuming that you want a one line csv file,
import json
def flattenjson(data, delim, topname=''):
"""JSON flattener that can handle embedded lists and dictionaries"""
flattened = {}
def internalflat(int_data, name=topname):
if type(int_data) is dict:
for key in int_data:
internalflat(int_data[key], name + key + delim)
elif type(int_data) is list:
i = 1
for elem in int_data:
internalflat(elem, name + str(i) + delim)
i += 1
else:
flattened[name[:-len(delim)]] = int_data
internalflat(data)
return flattened
#If you don't want mission or objective in csv file
flattened_astronauts = flattenjson(json.loads(datum)["Astronauts"], "__", "Astronaut")
keys = flattened_astronauts.keys().sort()
writer = csv.DictWriter(OD, keys ,restval='Null', delimiter=",", quotechar="\"", quoting=csv.QUOTE_ALL, dialect= "excel")
writer.writerow(flattened_astronauts)

Resources