在Windows上的Excel VBA中,对于已解析的JSON变量,这个JScriptTypeInfo究竟是什么?

时间:2016-06-08 19:20:15

标签: json excel vba

在这里回答我自己的问题 我已经在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.这是完整系列

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

Q2 In Excel VBA on Windows, how to loop through a JSON array parsed?

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

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

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

1 个答案:

答案 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。