如何在VBA Excel中以良好格式显示我的JSON对象

时间:2018-06-29 08:15:35

标签: json excel vba

我知道当Json是“简单的”(当它只是内部的字符串时)在单元格Excel中显示我的Parse Json,但是现在我有了String,对象和数组,我有点迷失了。 我的json如下:

[
    {
        "name": null,
        "type": null,
        "actions": [],
        "screen": null,
        "container": null,
        "sysid": 5,
        "uftitem": null
    },
    {
        "name": null,
        "type": null,
        "actions": [],
        "screen": null,
        "container": null,
        "sysid": 6,
        "uftitem": null
    },
    {
        "name": "UTProject5",
        "type": "type",
        "actions": [
            {
                "name": "UTProject",
                "description": "UTProject",
                "pattern": "UTProject",
                "isCheck": true,
                "sysid": 1,
                "uftaction": {
                    "sysid_uftAction": 2,
                    "code": "code uft",
                    "maxTime": 10,
                    "nbCycle": 20
                }
            },
            {
                "name": "UTProject2",
                "description": "UTProject",
                "pattern": "UTProject",
                "isCheck": true,
                "sysid": 3,
                "uftaction": {
                    "sysid_uftAction": 4,
                    "code": "code uft",
                    "maxTime": 10,
                    "nbCycle": 20
                }
            }
        ],
        "screen": {
            "name": null,
            "type": null,
            "actions": [],
            "screen": null,
            "container": null,
            "sysid": 5,
            "uftitem": null
        },
        "container": {
            "name": null,
            "type": null,
            "actions": [],
            "screen": null,
            "container": null,
            "sysid": 6,
            "uftitem": null
        },
        "sysid": 7,
        "uftitem": {
            "code": "code",
            "parentCode": "tooooz",
            "sysid": 8
        }
    },
    {
        "name": "UTProject6",
        "type": "type",
        "actions": [
            {
                "name": "UTProject",
                "description": "UTProject",
                "pattern": "UTProject",
                "isCheck": true,
                "sysid": 1,
                "uftaction": {
                    "sysid_uftAction": 2,
                    "code": "code uft",
                    "maxTime": 10,
                    "nbCycle": 20
                }
            },
            {
                "name": "UTProject2",
                "description": "UTProject",
                "pattern": "UTProject",
                "isCheck": true,
                "sysid": 3,
                "uftaction": {
                    "sysid_uftAction": 4,
                    "code": "code uft",
                    "maxTime": 10,
                    "nbCycle": 20
                }
            }
        ],
        "screen": {
            "name": null,
            "type": null,
            "actions": [],
            "screen": null,
            "container": null,
            "sysid": 5,
            "uftitem": null
        },
        "container": {
            "name": null,
            "type": null,
            "actions": [],
            "screen": null,
            "container": null,
            "sysid": 6,
            "uftitem": null
        },
        "sysid": 9,
        "uftitem": {
            "code": null,
            "parentCode": null,
            "sysid": 10
        }
    }
]

我想访问所需的内容并将其显示在单元格中,但我不知道对数组和对象的访问。

谢谢大家!

2 个答案:

答案 0 :(得分:3)

常规

您可以使用以下使用JSON converter的代码清空整个内容:


注意:

我正在从工作表中读取JSON字符串,并通过JSONConverter存储在对象中。初始对象是一个集合。我使用TypeName函数*循环该集合和每个嵌套级别,以确定在每个级别存储了哪些对象。然后,我使用Select Case适当地处理这些对象。

更有效的方法是设计一个可重用的类来处理此问题。我在SO上看到了其他一些问题。

* VarType实际上更强大


示例JSON

Example JSON


示例代码输出到立即窗口:

您可以通过将Debug.Print语句替换为工作表范围的分配来选择写入单元格的方式。

Sample code output


VBA:

Option Explicit
Public Sub GetInfoFromSheet()
    Dim jsonStr As String
    jsonStr = [A1]                               '<== read in from sheet
    Dim json As Object
    Set json = JsonConverter.ParseJson(jsonStr)

    Dim i As Long, j As Long, key As Variant
    For i = 1 To json.Count
        For Each key In json(i).keys
            Select Case key
            Case "name", "type"
                Debug.Print key & " " & json(i)(key)
            Case Else
                Select Case TypeName(json(i)(key))
                Case "Dictionary"
                    Dim key2 As Variant
                    For Each key2 In json(i)(key)
                        Select Case TypeName(json(i)(key)(key2))
                        Case "Collection"
                            Dim k As Long
                            For k = 1 To json(i)(key)(key2).Count
                                Debug.Print key & " " & key2 & " " & json(i)(key)(key2)(k)
                            Next k
                        Case Else
                            Debug.Print key & " " & key2 & " " & json(i)(key)(key2)
                        End Select
                    Next key2
                Case "Collection"
                    For j = 1 To json(i)(key).Count '<== "actions"
                        Dim key3 As Variant
                        For Each key3 In json(i)(key)(j).keys
                            Select Case TypeName(json(i)(key)(j)(key3))
                            Case "String", "Boolean", "Double"
                                Debug.Print key & " " & key3 & " " & json(i)(key)(j)(key3)
                            Case Else
                                Dim key4 As Variant
                                For Each key4 In json(i)(key)(j)(key3).keys
                                    Debug.Print key & " " & key3 & " " & key4 & " " & json(i)(key)(j)(key3)(key4)
                                Next key4
                            End Select
                        Next key3
                    Next j
                Case Else
                    Debug.Print key & " " & json(i)(key)
                End Select
            End Select
        Next key
    Next i
End Sub

tl; dr;教程点:

因此,上面的内容可能已经很完整了,因为它不需要任何解释就可以获取所有内容。下面,我们将更详细地介绍如何通过关联的VBA定位某些JSON和 “对话”

为此,您可以使用在线JSON解析器更清楚地查看JSON的结构。我将您的JSON字符串发布到Json Parser Online中,然后检查了String/parseJS eval中的结构;左侧部分。还有其他可用工具。

首先要注意的是开头"["。您可以在下面看到的第一个。

Start

这表示Collection对象,它是用JSON转换后的JsonConverter字符串。其他所有内容都嵌套在此"["开头的括号和末尾与其结尾的括号之间。

接下来要注意的是这是词典的集合,因此在其中形成“组”的所有内容都是字典。

Dictionary

看到"{"表示字典的开头吗?

字典的键为"name","type","actions"等。

最初的观察是,此信息很多都是空的。 null。 我们可以通过IsNull测试来忽略这些内容(我选择根据"name"字段执行此操作):

If Not IsNull(json(i)("name")) 

我们还可以看到"actions"不是"name"的字典中的null包含另一个字典集合。您会看到我们有"[",后跟"{",如前所述。

Collection of dictionaries

我们可以看到每个内部字典都具有"name", "description"等键。我们还可以看到它们的值具有不同的数据类型。

"actions"结构中观察JSON,您会发现它们是(使用示例字典):

  1. 字符串"name":"UTProject"
  2. 字符串"description":"UTProject"
  3. 字符串“ pattern":"UTProject"
  4. 布尔值"isCheck":true
  5. "sysid":1
  6. 字典"uftaction" 'keys of ==> "sysid_uftAction":2,"code":"code uft","maxTime":10,"nbCycle":20

因此,我们可以使用Select Case进行测试,以使用TypeName处理数据类型

对于原始布尔,字符串和双精度数据类型,我们可以简单地通过使用键将它们打印出来,例如

json(i)("actions")(j)("isCheck")

这将是TrueFalse. ij的布尔结果,它们是外部和内部集合的循环中当前位置的索引。

对于字典"uftaction",我们可以遍历其键:

For Each key2 In json(i)("actions")(j)(key).keys 
    Debug.Print "actions " & key & " " & key2 & " " & json(i)("actions")(j)(key)(key2)
Next key2

您当然可以使用密钥名称进行访问,而无需在末尾循环遍历密钥,例如:

json(i)("actions")(j)(key)("maxTime")

在整个过程中,您都可以通过索引而不是循环访问特定位置,这样ij将直接替换为数字值。对于任何给定的 key key, key2等都可以用实际的文字字符串替换。

希望这能给您更多的见识。

VBA:

Option Explicit
Public Sub GetInfoFromJSON()
    Dim jsonStr As String
    jsonStr = [A1]                               '<== read in from sheet
    Dim json As Object, i As Long
    Set json = JsonConverter.ParseJson(jsonStr) '<==This is a collection verified by Debug.Print TypeName(JSON)
    For i = 1 To json.Count
        If Not IsNull(json(i)("name")) Then
            'ignore the null names which have sys id only populated
            Debug.Print "name" & " " & json(i)("name")
            Debug.Print "type" & " " & json(i)("type")
            Dim j As Long
            For j = 1 To json(i)("actions").Count 'actions are a collection of dictionaries
                Dim key As Variant
                For Each key In json(i)("actions")(j).keys 'dictionary
                    'observing actions in the JSON structure you can see there are:
                    '                    String  "name":"UTProject"
                    'String "description":"UTProject",
                    'String "pattern":"UTProject",
                    'Boolean "isCheck":true,
                    'Double "sysid":1,
                    'Dictionary "uftaction" '==> "sysid_uftAction":2,"code":"code uft","maxTime":10,"nbCycle":20
                    'So we can use Select Case to handle the data type by testing with TypeName
                    Select Case TypeName(json(i)("actions")(j)(key))
                    Case "String", "Boolean", "Double" '<==good to go nothing extra needed
                        Debug.Print "actions " & key & " " & json(i)("actions")(j)(key)
                    Case Else                    ' we are dealing with uftaction which we know is a dictionary
                        Dim key2 As Variant
                        For Each key2 In json(i)("actions")(j)(key).keys '<==We know now we are looping the uftaction dictionary which has keys "sysid_uftAction","code","maxTime","nbCycle"
                            Debug.Print "actions " & key & " " & key2 & " " & json(i)("actions")(j)(key)(key2)
                        Next key2
                    End Select
                Next key
            Next j
        End If
    Next i
End Sub

答案 1 :(得分:0)

看下面的例子。 JSON.bas模块导入VBA项目中以进行JSON处理。

Option Explicit

Sub Test()

    Dim sJSONString As String
    Dim vJSON
    Dim sState As String
    Dim aData()
    Dim aHeader()
    Dim vResult

    ' Read JSON sample from file C:\Test\sample.json
    sJSONString = ReadTextFile("C:\Test\sample.json", 0)
    ' Parse JSON sample
    JSON.Parse sJSONString, vJSON, sState
    If sState = "Error" Then
        MsgBox "Invalid JSON"
        End
    End If
    ' Convert raw JSON to 2d array and output to worksheet #1
    JSON.ToArray vJSON, aData, aHeader
    With Sheets(1)
        .Cells.Delete
        .Cells.WrapText = False
        OutputArray .Cells(1, 1), aHeader
        Output2DArray .Cells(2, 1), aData
        .Columns.AutoFit
    End With
    ' Flatten JSON
    JSON.Flatten vJSON, vResult
    ' Convert flattened JSON to 2d array and output to worksheet #2
    JSON.ToArray vResult, aData, aHeader
    With Sheets(2)
        .Cells.Delete
        .Cells.WrapText = False
        OutputArray .Cells(1, 1), aHeader
        Output2DArray .Cells(2, 1), aData
        .Columns.AutoFit
    End With
    MsgBox "Completed"

End Sub

Sub OutputArray(oDstRng As Range, aCells As Variant)

    With oDstRng
        .Parent.Select
        With .Resize(1, UBound(aCells) - LBound(aCells) + 1)
            .NumberFormat = "@"
            .Value = aCells
        End With
    End With

End Sub

Sub Output2DArray(oDstRng As Range, aCells As Variant)

    With oDstRng
        .Parent.Select
        With .Resize( _
                UBound(aCells, 1) - LBound(aCells, 1) + 1, _
                UBound(aCells, 2) - LBound(aCells, 2) + 1)
            .NumberFormat = "@"
            .Value = aCells
        End With
    End With

End Sub

Function ReadTextFile(sPath As String, lFormat As Long) As String

    ' lFormat -2 - System default, -1 - Unicode, 0 - ASCII
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(sPath, 1, False, lFormat)
        ReadTextFile = ""
        If Not .AtEndOfStream Then ReadTextFile = .ReadAll
        .Close
    End With

End Function

顺便说一句,类似的方法适用于以下答案:1234567891011121314,{{ 3}},15161718