在VBA

时间:2017-09-14 17:46:38

标签: json vba excel-vba jsonparser excel

问题

描述

我目前遇到的问题是,我要回的JSON字段是空的。

在下面的代码中,我发现大部分字段都有受让人,而另一级受让人有一个displayName。我还发现有些东西没有受让人。当发生这种情况时(并且这可能会发生在其他字段中,我只是将其作为示例),它会删除额外的层次级别和实际路径(也会显示)下面)会改变。

问题

有没有一种简单的方法来迭代这个响应,并将空值设置为空白?

Set Json = JsonConverter.ParseJson(MyRequest.ResponseText)

但这并不能帮助我实现自动化。请注意[下面]我将组件列出两次,因为我不知道如何遍历该数据并将字段拉回到需要填充的次数。 Aka我知道有两个组件,但它只带回一个组件,因此我必须复制该代码才能使其正常工作(我很抱歉复制)。

Code Snip

我的代码很有效,直到它达到null,然后它会抛出错误。

''''''''
' Loop '
''''''''

    For i = 0 To 40

'        ActiveSheet.Cells(i + 1, 1) = Json("issues")(i + 1)("fields")("issuetype")("name")
'        ActiveSheet.Cells(i + 1, 2) = Json("issues")(i)("key")
'        ActiveSheet.Cells(i + 1, 3) = Json("issues")(i + 1)("fields")("summary")
'        ActiveSheet.Cells(i + 1, 4) = Json("issues")(i + 1)("fields")("status")("name")
         ActiveSheet.Cells(i + 1, 5) = Json("issues")(i + 1)("fields")("assignee")
         ActiveSheet.Cells(i + 1, 5) = Json("issues")(i + 1)("fields")("assignee")("displayName")
'        ActiveSheet.Cells(i + 1, 6) = Json("issues")(i + 1)("fields")("customfield_13301")
'        ActiveSheet.Cells(i + 1, 7) = Json("issues")(i + 1)("fields")("components")(1)("name")
'        ActiveSheet.Cells(i + 1, 8) = Json("issues")(i + 1)("fields")("components")(2)("name")
'        ActiveSheet.Cells(i + 1, 9) = Json("issues")(i + 1)("fields")("customfield_13300")
'        ActiveSheet.Cells(i + 1, 10) = Json("issues")(i + 1)("fields")("customfield_10002")
    Next i

JSON

由于隐私原因,我不得不删除一些内容,但这表明受让人为空。带有a," displayName"的JSON;只需将null转换为数组,并在其下有更多字段。

{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 52,
"issues": [
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id": "92110",
"self": "",
"key": "",
"fields": {
"customfield_13100": null,
"fixVersions": [],
"customfield_13500": null,
"customfield_11200": null,
"resolution": null,
"customfield_13502": null,
"customfield_13501": null,
"lastViewed": null,
"customfield_12000": null,
"customfield_12002": null,
"customfield_12001": null,
"priority": {},
"customfield_10100": null,
"customfield_10101": null,
"customfield_12003": null,
"customfield_12402": null,
"labels": [],
"customfield_11303": null,
"customfield_11305": null,
"customfield_11306": null,
"aggregatetimeoriginalestimate": null,
"timeestimate": null,
"versions": [],
"issuelinks": [],
"assignee": null,
"status": {},
"components": [],
"customfield_13200": null,
"customfield_13600": null,
"customfield_12900": null,
"aggregatetimeestimate": null,
"creator": {},
"customfield_14000": null,
"subtasks": [],
"customfield_14400": null,
"reporter": {},
"customfield_12101": null,
"customfield_12100": null,
"aggregateprogress": {},
"customfield_14401": null,
"customfield_14402": null,
"customfield_12500": null,
"customfield_13702": null,
"customfield_13704": null,
"customfield_13703": null,
"customfield_11802": null,
"progress": {},
"votes": {},
"issuetype": {},
"timespent": null,
"project": {},
"customfield_13300": null,
"aggregatetimespent": null,
"customfield_13302": null,
"customfield_13301": null,
"customfield_13700": null,
"customfield_11400": null,
"resolutiondate": null,
"workratio": -1,
"watches": {},
"created": "2017-07-21T08:04:42.000-0500",
"customfield_14102": null,
"customfield_10020": null,
"customfield_12200": null,
"customfield_14100": null,
"customfield_14101": null,
"customfield_12600": null,
"customfield_14500": null,
"customfield_10300": null,
"customfield_10016": null,
"customfield_13405": null,
"customfield_10017": null,
"customfield_13800": null,
"customfield_10018": null,
"customfield_10019": null,
"customfield_13409": null,
"updated": "2017-08-10T15:29:37.000-0500",
"timeoriginalestimate": null,
"description": null,
"customfield_10011": null,
"customfield_10012": null,
"customfield_13401": null,
"customfield_13400": null,
"customfield_10013": null,
"customfield_10014": null,
"customfield_11500": "{}",
"customfield_10015": null,
"customfield_13514": null,
"summary": "",
"customfield_14200": null,
"customfield_10000": null,
"customfield_13511": null,
"customfield_12301": null,
"customfield_10001": null,
"customfield_12300": null,
"customfield_10002": "1|i021pe:5z",
"customfield_13510": null,
"customfield_13513": null,
"customfield_10003": [],
"customfield_12302": null,
"customfield_10004": null,
"customfield_13504": null,
"customfield_13503": null,
"customfield_11600": null,
"customfield_13506": null,
"environment": null,
"customfield_13901": null,
"customfield_13505": null,
"customfield_13508": null,
"duedate": null,
"customfield_13509": null
}
},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{}
]
}

其他数据

我查看了Raw文件,看看是否有任何不同(比我在JSON Formater Plugin for Chrome 中所做的那样),这就是它的样子:

"assignee":null,

3 个答案:

答案 0 :(得分:2)

如果您了解JsonConverter如何将JSON处理为复合对象,则使用JSON文件会更容易(恕我直言)。让我们看一个简单的JSON格式(取自this useful site):

{
  "array": [
    1,
    2,
    3
  ],
  "boolean": true,
  "null": null,
  "number": 123,
  "object": {
    "a": "b",
    "c": "d",
    "e": "f"
  },
  "string": "Hello World"
}

JsonConverter将每个数据项映射到他们的VBA对应物中。

"array"   maps to Collection   (anytime you see the square brackets [])
"boolean" maps to Boolean
"null"    maps to Null
"number"  maps to Double
"object"  maps to Dictionary   (anytime you see the curly braces {})
"string"  maps to String

现在我们可以使用您的JSON示例执行有用的操作,例如通过

确定"issues"数组中有多少个entires
Dim issues As Collection
Set issues = schema("issues")
Debug.Print issues.Count

"issues"数组中的每个条目实际上都是一个复合对象,因此它是Dictionary。因此,我们可以这样做:

Dim issue As Variant
For Each issue In issues
    If issue.Exists("id") Then
        Debug.Print "id = " & issue("id")
    End If
Next issue

当然,此单"fields"的{​​{1}}部分本身就是另一个issue。因此,堆叠字典引用我们也可以这样做:

Dictionary

所有这些都是背景,希望能够更轻松地访问JSON结构的成员。您真正的问题是处理Debug.Print "field summary is " & issue("fields")("summary") 。如果字段的实际值设置为NULLs(请参阅上面的示例),那么您可以这样检查

null

在我们将它们放在一起之前的其他一些附注:

  1. 始终使用If IsNull(issue("fields")("customfield_13500")) Then ...
  2. 避免使用Option ExplicitSelect
  3. 始终定义和设置对所有工作簿和表格的引用
  4. 在下面的示例中,您会看到我假设您必须检查Activate的每个字段。最好通过在子例程中隔离该检查而不是使用一长串Null语句使代码过度混乱来实现。下面的代码示例的优点是您不必硬编码问题的数量,因为您的逻辑可以检测到有多少问题。

    If

答案 1 :(得分:0)

修复

这就是我为此付出的努力:

{{1}}

答案 2 :(得分:0)

您可以将JSON数据导入数组,如下面的示例代码所示。 JSON.bas模块导入VBA项目以进行JSON处理。

Sub Test()

    ' Put sourse JSON string to "\source.json" file, and save as ANSI or Unicode

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

    sJSONString = ReadTextFile(ThisWorkbook.Path & "\source.json", -2)
    JSON.Parse sJSONString, vJSON, sState
    vJSON = vJSON("issues")
    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

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