【问题标题】:how to display my JSON object in good format in VBA Excel如何在 VBA Excel 中以良好的格式显示我的 JSON 对象
【发布时间】:2020-01-03 07:53:36
【问题描述】:

我知道当 Json 是“简单”时(当它只是内部的字符串时)在单元格 Excel 中显示我的 Parse Json,但现在我有字符串、对象和数组,我有点迷路了.. 我的 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
        }
    }
]

我想访问我想要的并在单元格中显示它,但我不知道在数组和对象中的访问。

谢谢大家!

【问题讨论】:

    标签: json excel vba


    【解决方案1】:

    一般:

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


    注意:

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

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

    * VarType 实际上更健壮


    JSON 示例


    输出到即时窗口的示例代码:

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


    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;博士;教程点:

    所以上面的内容可能有点完整,因为它没有太多解释就得到了一切。下面,我们将更详细地了解如何通过相关的 VBA 来定位其中的一些 JSON 和“对话”

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

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

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

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

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

    字典有"name","type","actions"等键。

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

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

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

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

    观察JSON 结构中的"actions",您可以看到这些是(使用示例字典):

    1. 字符串"name":"UTProject"
    2. 字符串"description":"UTProject"
    3. 字符串“pattern":"UTProject"
    4. 布尔值"isCheck":true
    5. "sysid":1
    6. 字典"uftaction" 'keys of ==&gt; "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, key2 等可以替换为任何给定 key 的实际文字字符串。

    希望这能给你更多的见解。

    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
    

    【讨论】:

    • 好帖子。非常彻底,而且VBA+JSON资源有限,这样的东西对很多人都有用
    【解决方案2】:

    看看下面的例子。 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
    

    顺便说一句,类似的方法适用于in other answers

    【讨论】:

      猜你喜欢
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2018-11-17
      相关资源
      最近更新 更多