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

后端 未结 1 1280
野趣味
野趣味 2020-11-29 12:47

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.co

相关标签:
1条回答
  • 2020-11-29 13:12

    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:\wINDOWS\SysWOW64\msscript.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:\wINDOWS\SysWOW64\jscript.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:\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
    

    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.

    0 讨论(0)
提交回复
热议问题