在这里回答我自己的问题 我已经在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解决方案的偏好。
以下是此问题构建的先前问题In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?。它显示了如何使用VBA.CallByName更健壮 而不是使用点语法来遍历解析的JSON对象。另外一个先前的问题In Excel VBA on Windows, how to loop through a JSON array parsed?显示了它也可以如何 用于访问数组元素。但是CallByName返回一个好奇的变量类型,它在Watch窗口中显示为Object / JScriptTypeInfo 如果在即时窗口中键入一个Debug.Print(或将鼠标悬停在变量上),则会得到无信息的“[object Object]”。在另一个问题 在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”?中,在调查时 如何查询成员的JSON对象我发现似乎附加到JScriptTypeInfo对象的hasOwnProperty()方法。
所以在这个问题中我问,究竟这个JScriptTypeInfo究竟是什么?
这是5系列的问题5.这是完整系列
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 :(得分:5)
要查看的一个可能的地方是ScriptControl的类型库,因为这是发出此类型的库。
我机器上此类型的完整详情
Libary Name: Microsoft Script Control 1.0 (Ver 1.0)
LIBID: {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}
Location: C:\wINDOWS\SysWOW64\msscript.ocx
使用VBA IDE的对象浏览器和反汇编类型库的OLEVIEW.exe,我无法跟踪JScriptTypeInfo接口或方法hasOwnProperty。
但是,脚本引擎是否承载语言实现,例如VBScript和JScript(Javascript的Microsoft名称)。 所以也许我们应该寻找一个JScript实现DLL,实际上这里有一个细节
Libary Name: Microsoft JScript Globals
LIBID: {3EEF9759-35FC-11D1-8CE4-00C04FC2B085}
Location: C:\wINDOWS\SysWOW64\jscript.dll
我的机器上没有注册,因此不在我的工具列表 - >参考库或OLEVIEW.exe中。我很幸运,一边寻找一边 这是OLEVIEW的一些输出,给出了类型库的异常
[
uuid(3EEF9758-35FC-11D1-8CE4-00C04FC2B097)
]
dispinterface ObjectInstance {
properties:
methods:
[id(0x0000044c)]
StringInstance* toString();
[id(0x0000044d)]
StringInstance* toLocaleString();
[id(0x0000044e)]
VARIANT hasOwnProperty(VARIANT propertyName);
[id(0x0000044f)]
VARIANT propertyIsEnumerable(VARIANT propertyName);
[id(0x00000450)]
VARIANT isPrototypeOf(VARIANT obj);
[id(0x00000451)]
ObjectInstance* valueOf();
};
上面显示hasOwnProperty是一个IDispatch接口(或dispinterface)的方法,它可以处理声明为Object类型的VBA对象(例如Dim foo as Object
)
使用regsvr32注册类型库似乎什么都不做。必须浏览到工具参考中的文件才能在VBA的对象浏览器中查看。
我们可以非常确定这个JScript.dll文件,因为使用Process Explorer我们可以在执行行oScriptEngine.Language = "JScript"
时看到正在加载的dll
在缺少已注册的类型库的情况下,我将文件JScript.dll加载到Notepad ++中,并将.J.S.c.r.i.p.t.T.y.p.e.I.n.f.o作为正则表达式进行搜索并找到了匹配项。宾果!
不仅有一个ObjectInstance可以描述VBA程序遇到的大多数变量,而且还有一个有趣的ArrayInstance,也许我们可以使用Javascript自己的数组函数 或者至少是JScript.dll类型库中记录的子集。这是一些示例代码
'Tools->References->
'Microsoft Script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx
'and FYI/browsing capabilities Microsoft JScript Globals; C:\wINDOWS\SysWOW64\jscript.dll
Option Explicit
Private Sub TestJSONParsingWithCallByName5()
Dim oScriptEngine As ScriptControl
Set oScriptEngine = New ScriptControl
oScriptEngine.Language = "JScript"
Dim sJsonString(0 To 1) As String
sJsonString(0) = "{'key1': 'value1' ,'key2': { 'key3': 'value3' } }"
sJsonString(1) = "[ 1234, 2345, 3456, 4567, 5678, 6789 ]"
Dim objJSON(0 To 1) As Object
Set objJSON(0) = oScriptEngine.Eval("(" + sJsonString(0) + ")")
Set objJSON(1) = oScriptEngine.Eval("(" + sJsonString(1) + ")")
Debug.Assert objJSON(0).hasOwnProperty("key1")
Debug.Assert objJSON(0).hasOwnProperty("key2")
Debug.Assert CallByName(objJSON(1), "length", VbGet) = 6
Debug.Assert CallByName(objJSON(1), "0", VbGet) = "1234"
'* Is objJSON(1) an ArrayInstance?
'* does it support the reverse method of the ArrayInstance object?
'Call objJSON(1).Reverse '* reverse gets capitalised into Reverse ... grrrr
Call CallByName(objJSON(1), "reverse", VbMethod) '* so use CallByName as solution to "helpful" capitalisation
'* Yes, the elements are reversed!
Debug.Assert CallByName(objJSON(1), "length", VbGet) = 6
Debug.Assert CallByName(objJSON(1), "0", VbGet) = "6789"
Stop
'** And now we know objJSON(1) is an ArrayInstance we can have some fun with array operations
Dim objSplice As Object
Set objSplice = CallByName(objJSON(1), "splice", VbMethod, 2, 1)
Debug.Assert CallByName(objJSON(1), "length", VbGet) = 5
Debug.Assert CallByName(objSplice, "length", VbGet) = 1
Dim objSlice As Object
Set objSlice = CallByName(objJSON(1), "slice", VbMethod, 2)
Debug.Assert CallByName(objJSON(1), "length", VbGet) = 5
Debug.Assert CallByName(objSlice, "length", VbGet) = 3
Stop
Call CallByName(objJSON(1), "sort", VbMethod)
Debug.Assert CallByName(objJSON(1), "join", VbMethod) = "1234,2345,3456,5678,6789"
Debug.Assert CallByName(objJSON(1), "join", VbMethod, " ") = "1234 2345 3456 5678 6789"
Stop
Debug.Assert CallByName(objJSON(1), "pop", VbMethod) = "6789"
Debug.Assert CallByName(objJSON(1), "length", VbGet) = 4
Stop
End Sub
摘要:JScriptTypeInfo是在VBA IDE监视窗口中显示的内容以及VBA函数TypeName()的返回,但它实际上隐藏了可在JScript.dll中找到的许多对象。
我认为它可以被描述为多态,也许更好地将其描述为后期绑定。要查看功能,请使用Tools-References并浏览到JScript.dll。