Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
610 views
in Technique[技术] by (71.8m points)

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

answering my own question here.
I have done some work with JSON in Excel VBA and lots of findings to post which I will do so in Q & A format https://stackoverflow.com/help/self-answer https://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/

So elsewhere on stackoverflow one can see questions about parsing JSON in VBA but they seem to miss a trick or two.

To begin with, I resile from using custom JSON parsing libraries and instead use the ScriptControl's Eval method as the basis of all my JSON code. And also we express a preference from native Microsoft solutions.

Here is a prior question In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour? upon which this question builds. It shows how using VBA.CallByName is more robust than using the dot syntax to traverse a parsed JSON object. Also another prior question In Excel VBA on Windows, how to loop through a JSON array parsed? shows how it also can be used to access array elements. But CallByName returns a curious variable type that appears in Watch window as Object/JScriptTypeInfo and if one type Debug.Print in the immediate window (or hovers over the variable) one gets the uninformative "[object Object]". In another question in the series In Excel VBA on Windows, how to get stringified JSON respresentation instead of “[object Object]” for parsed JSON variables? I present some debugging "sugar" that allows nice inspection of variables. In a fourth question In Windows Excel VBA,how to get JSON keys to pre-empt “Run-time error '438': Object doesn't support this property or method”?, whilst investigating how to query a JSON object for a member I discover a hasOwnProperty() method that seems attached to a JScriptTypeInfo object.

So in this question I ask, what exactly is this JScriptTypeInfo anyway?

This is Question 5 of series of 5. Here is the full series

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One possible place to look is in the type library for the ScriptControl as this is the library which emanates this type.

The full details of this type on my machine are

Libary Name:    Microsoft Script Control 1.0 (Ver 1.0)       
LIBID:          {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}
Location:       C:wINDOWSSysWOW64msscript.ocx 

Using both VBA IDE's Object Browser and OLEVIEW.exe which disassembles type library I can no trace of the interface JScriptTypeInfo or the method hasOwnProperty.

But isn't it the case that the script engine hosts language implementations, such as VBScript and JScript (Microsoft name for Javascript).
So perhaps we should hunt for a JScript implementation DLL and indeed there is one here are details

Libary Name:    Microsoft JScript Globals
LIBID:          {3EEF9759-35FC-11D1-8CE4-00C04FC2B085}
Location:       C:wINDOWSSysWOW64jscript.dll 

which on my machine is not registered and so not in my list of Tools->References libraries or in OLEVIEW.exe. I was lucky to find whilst poking around.
Here is some output from OLEVIEW giving an exceprt of the type library

[
  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();
};

This above shows the hasOwnProperty to be a method of a IDispatch interface (or dispinterface) necessary to work with VBA object's declared of type Object (e.g. Dim foo as Object) Registering the type library with regsvr32 appears to do nothing. One must browse to the file in Tools References to view in VBA's object browser.

We can be pretty sure about this JScript.dll file because using Process Explorer we can see the dll being loaded when executing the line oScriptEngine.Language = "JScript" In the lack of a registered type library I loaded the file JScript.dll into Notepad++ and searched for .J.S.c.r.i.p.t.T.y.p.e.I.n.f.o as a regular expression and found a hit. Bingo!

Not only is there an ObjectInstance which would describe most of the variables a VBA program encounters but also there is an ArrayInstance which is intriguing, perhaps we can use Javascript's own array functions or at least a subset as documented in JScript.dll's type library. Here is some sample code

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

'and FYI/browsing capabilities       Microsoft JScript Globals;   C:wINDOWSSysWOW64jscript.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

SUMMARY: JScriptTypeInfo is something to show in the VBA IDE watch window and the return of the VBA function TypeName() but which really hides a number of objects that can be found in JScript.dll.
I suppose it can be described as polymorphic, perhaps better to describe it as late binding. To view capabilities use Tools-References and browse to JScript.dll.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...