在Windows上的Excel VBA中,如何减轻由IDE的大小写行为破坏的解析JSON的点语法遍历问题?
嗨,在这里回答我自己的问题。我已经在Excel VBA中使用JSON做了一些工作,并发布了大量的发现,我将在Q&格式 https://stackoverflow.com/help/self-answer http://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"并且此代码有效,直到一个取消注释
'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行之后,Line1将被重写为符号' 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和JBA中进行JSON解析的知识 (2)如果有人发现如何停止资本化,那么这显然是赢家。
这是5系列的问题1.这是完整系列
Q2 In Excel VBA on Windows, how to loop through a JSON array parsed?
Q5 In Excel VBA on Windows, for parsed JSON variables what is this JScriptTypeInfo anyway?
答案 0 :(得分:2)
最后,我使用了原生的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