【问题标题】:In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?在 Windows 上的 Excel VBA 中,如何缓解 IDE 的大写行为破坏已解析 JSON 的点语法遍历问题?
【发布时间】:2016-10-09 05:21:22
【问题描述】:

在 Windows 上的 Excel VBA 中,如何缓解 IDE 的大写行为破坏已解析 JSON 的点语法遍历问题?

嗨,在这里回答我自己的问题。我在 Excel VBA 中使用 JSON 完成了一些工作,并发布了许多发现,我将以问答格式进行发布 https://stackoverflow.com/help/self-answerhttps://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/

所以在 stackoverflow 的其他地方可以看到有关在 VBA 中解析 JSON 的问题,但他们似乎错过了一两个技巧。

首先,我放弃使用自定义 JSON 解析库,而是使用 ScriptControl 的 Eval 方法作为我所有 JSON 代码的基础。 我们还表达了对原生 Microsoft 解决方案的偏好。

在第一个问题中,我将展示在 Excel VBA 中,实际上可以使用点语法来遍历 JSON 结构,但不幸的是,这是 被 VBA IDE 在大写方面的“帮助”所打破。

下面是一些示例代码,在标记为 1 的行上:我们可以看到文本“objJSON.key1”,并且此代码一直有效,直到一个 uncmets

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Option Explicit
Option Private Module

Private Sub TestJSONParsingWithVBACallByName()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"
    
    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"
    
    
    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")
1:  Debug.Assert objJSON.key1 = "value1"
    Debug.Assert objJSON.key2.key3 = "value3"
    
    '**** BUT IF UNCOMMENT NEXT LINE THIS AFFECTS ALL CAPITALISATION INSTANCES OF KEY1 INCLUDING LINE 1 WHICH THENCE BREAKS
2:  'Dim Key1 as Long

End Sub

这是之前的截图 在取消注释第 2 行之后,第 1 行被重写为符号“key1”,现在给定一个大写字母“K”。

现在经过一些实验,似乎重写效果仅限于项目范围,因此其他项目不受影响。 这意味着人们可以通过始终使用单独的项目来隔离问题,但是如何将对象编组到使用项目和 从那里访问它,肯定会再次遇到同样的问题。因此,项目隔离并不是真正的解决方案。

一种方法是确保符号不冲突,并为 JSON 键提供某种前缀,因此这里是一个示例

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Private Sub TestJSONParsingWithDotSyntaxAndKeyPrefixesToAvoidNameClash()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"
    
    Dim sJsonString As String
    sJsonString = "{'kKey1': 'value1'  ,'kKey2': { 'kKey3': 'value3' } }"
    
    
    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")
1:  Debug.Assert objJSON.kKey1 = "value1"
    Debug.Assert objJSON.kKey2.kKey3 = "value3"
    
    '**** SAFE TO UNCOMMENT AS SYMBOLS DO NOT CLASH NOW
2:  'Dim Key1 As Long
End Sub

不知何故,我不喜欢这样,必须更改 JSON 以便 VBA 可以访问它似乎很奇怪。此外,可能无法控制源 JSON。

还有其他方法,例如在脚本引擎中添加一些 javscript 以允许 Javascript 进行访问。向用户 Codo https://stackoverflow.com/users/413337/codo 致敬,这里有一个基于这种方法的示例...

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Private Sub TestJSONParsingWithMiniScript()
    'hat tip to Codo https://stackoverflow.com/users/413337/codo
    'Based on https://stackoverflow.com/questions/5773683/excel-vba-parsed-json-object-loop#7300963  
    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"
    oScriptEngine.AddCode "function getProperty(jsonObj, propertyName) { return jsonObj[propertyName]; } "


    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"
    
    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")
    Debug.Assert oScriptEngine.Run("getProperty", objJSON, "key1") = "value1"
    Debug.Assert oScriptEngine.Run("getProperty", oScriptEngine.Run("getProperty", objJSON, "key2"), "key3") = "value3"

End Sub

我喜欢将脚本添加到脚本引擎的技术,但是我发现了一种更原生的技术,那就是使用 VBA.CallByName 这就是我的回答中显示的技术。

我没有选择我自己的答案作为确定的答案,因为我认为 (1) 社区似乎可以继续提高我们在 Excel VBA 中解析 JSON 的知识和 (2) 如果有人发现了如何阻止大写,那显然是赢家。

这是系列 5 的问题 1。这是完整系列

第一季度In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?

第二季度In Excel VBA on Windows, how to loop through a JSON array parsed?

第三季度In Excel VBA on Windows, how to get stringified JSON respresentation instead of “[object Object]” for parsed JSON variables?

第四季度In Windows Excel VBA,how to get JSON keys to pre-empt “Run-time error '438': Object doesn't support this property or method”?

Q5In Excel VBA on Windows, for parsed JSON variables what is this JScriptTypeInfo anyway?

【问题讨论】:

标签: json excel vba


【解决方案1】:

最后,我使用本机 VBA.CallByName 进行了以下操作

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Private Sub TestJSONParsingWithCallByName()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"


    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")
    Debug.Assert VBA.CallByName(objJSON, "key1", VbGet) = "value1"
    Debug.Assert VBA.CallByName(VBA.CallByName(objJSON, "key2", VbGet), "key3", VbGet) = "value3"

End Sub

【讨论】:

  • Debug.Assert 调用不应该有副作用。您应该将结果提取到局部变量中,并在单独的指令中断言这些局部变量。 Debug 调用应该被视为仅存在于那里的代码,好吧,用于调试目的;让它们运行你的实际逻辑是不对的。
  • 感谢收看。我一直使用 Debug.Asserts 没有任何不良影响。
  • 我并不是说不要使用Debug.Assert。我是说您应该能够从代码中完全删除 Debug.Assert 调用,而不会以任何方式改变其行为。
  • 好的,我同意在投入生产之前删除它们。通常它们位于我的测试脚本中,而不是主代码中。我在这里使用它们,以便读者可以看到表达式的值。
  • 看看how to get the best value of Code ReviewSimon's checklist for writing a good Code Review question - 当然,该网站的help center 应该回答您的大部分问题,如果不是全部的话。如果您想聊聊该网站和/或与常客见面,也可以随时加入The 2nd Monitor! =)
猜你喜欢
  • 2016-10-09
  • 1970-01-01
  • 2013-12-04
  • 2014-04-03
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
相关资源
最近更新 更多