2016-06-08 5 views
4

Beantwortung meiner eigenen Frage hier.
Ich habe einige Arbeit mit JSON in Excel VBA und viele Erkenntnisse getan zu schreiben, die ich in Q so tue & A-Format https://stackoverflow.com/help/self-answerhttp://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/In Excel VBA unter Windows, für geparste JSON-Variablen, was ist das JScriptTypeInfo überhaupt?

So anderswo auf Stackoverflow eine Frage zum Parsen von JSON in VBA sehen kann, aber sie scheinen einen oder zwei Tricks zu verpassen.

Zunächst kann ich keine benutzerdefinierten JSON-Parsing-Bibliotheken verwenden und stattdessen die Eval-Methode von ScriptControl als Grundlage für meinen gesamten JSON-Code verwenden. Und auch wir drücken eine Präferenz von nativen Microsoft-Lösungen aus.

Hier ist eine vorherige Frage In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?, auf der diese Frage aufbaut. Es zeigt, wie die Verwendung von VBA.CallByName robuster ist als die Verwendung der Punktsyntax zum Durchlaufen eines analysierten JSON-Objekts. Auch eine andere Vorfrage In Excel VBA on Windows, how to loop through a JSON array parsed? zeigt, wie man auch zum Zugriff auf Array-Elemente verwenden kann. Aber CallByName gibt einen kuriosen Variablentyp zurück, der im Watch-Fenster als Object/JScriptTypeInfo erscheint und wenn man Debug.Print im unmittelbaren Fenster eingibt (oder über die Variable schwebt) erhält man das nicht informative "[object Object]". In einer anderen Frage in der Reihe In Excel VBA on Windows, how to get stringified JSON respresentation instead of “[object Object]” for parsed JSON variables? Ich präsentiere einige Debugging "Zucker", die eine gute Überprüfung der Variablen ermöglicht. In einer vierten Frage In Windows Excel VBA,how to get JSON keys to pre-empt “Run-time error '438': Object doesn't support this property or method”?, während der Untersuchung , wie ein JSON-Objekt für ein Mitglied abfragen, entdecke ich eine hasOwnProperty() -Methode, die an ein JScriptTypeInfo-Objekt angefügt scheint.

Also in dieser Frage frage ich, was genau ist das JScriptTypeInfo überhaupt?

Dies ist Frage 5 der Serie von 5. Hier ist die vollständige Reihe

Q1 ist 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?

+0

WSH Der globale JScript-Objekttyp ist 'JScriptTypeInfo' (mit anderen Worten das globale' this' Objekt). BTW, VBScript hat das gleiche globale Objekt 'Me' vom Typ' VBScriptTypeInfo' und ermöglicht das dynamische Erstellen von Prozeduren, Funktionen, Klassen und sogar Klassen innerhalb von Funktionen. – omegastripes

Antwort

5

Ein möglicher Ort zum Suchen ist in der Typbibliothek für das ScriptControl, da dies die Bibliothek ist, die diesen Typ ausgibt.

Die vollständigen Details dieser Art auf meiner Maschine sind

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

Mit beiden Object Browser der VBA-IDE und Oleview.exe die Typbibliothek auseinanderbauen kann ich keine Spur von der Schnittstelle JScriptTypeInfo oder die Methode hasOwnProperty.

Aber ist das nicht der Fall, dass die Skript-Engine Sprachimplementierungen wie VBScript und JScript (Microsoft-Name für Javascript) hostet.
Also sollten wir vielleicht für eine JScript Implementierung DLL jagen und in der Tat gibt es hier einen sind Details

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

, die auf meinem Rechner nicht registriert ist und so nicht in meiner Liste der Tools-> Referenzen Bibliotheken oder in OLEVIEW. exe. Ich war glücklich zu finden, während herum stochern.
Hier einige Ausgabe von OLEVIEW eine exceprt der Typbibliothek

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

ein Verfahren zur Herstellung einer IDispatch-Schnittstelle (oder dispinterface) notwendig, um die Arbeit mit VBA Objekt Das oben zeigt die hasOwnProperty geben vom Typ Object deklariert zu sein (zB Dim foo as Object) Das Registrieren der Typbibliothek mit regsvr32 scheint nichts zu tun. Man muss zu der Datei in Tools References navigieren, um sie im VBA-Objektbrowser anzuzeigen.

Wir können ziemlich sicher sein, diese JScript.dll Datei weil Process Explorer verwenden wir die DLL geladen wird sehen können, wenn die Linie oScriptEngine.Language = "JScript" Im Fehlen einer registrierten Typbibliothek Ausführung geladen ich die Datei JScript.dll in Notepad ++ und Nach .JScriptTypeInfo als regulärer Ausdruck gesucht und einen Treffer gefunden. Bingo!

Nicht nur gibt es eine ObjectInstance, die die meisten Variablen beschreibt, die ein VBA-Programm findet, sondern auch eine ArrayInstance, die faszinierend ist. Vielleicht können wir Javascript eigene Array-Funktionen oder zumindest eine Teilmenge wie in JScript dokumentiert verwenden. DLL-Typ-Bibliothek. Hier ist ein Beispielcode

'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 

ZUSAMMENFASSUNG: JScriptTypeInfo etwas ist in der VBA-IDE Ãœberwachungsfenster und die Rückkehr der VBA-Funktion Type-Name anzuzeigen(), aber das ist wirklich verbirgt sich eine Reihe von Objekten, die in JScript zu finden sind. DLL.
Ich nehme an, dass es als polymorph beschrieben werden kann, vielleicht besser, es als späte Bindung zu beschreiben. Verwenden Sie Tools-References, um Funktionen anzuzeigen, und navigieren Sie zu JScript.dll.

+0

Ist der Typ 'JScriptTypeInfo' wirklich in' JScript.dll' definiert? Wenn ich diese DLL in OLEVIEW geöffnet habe, ist dort kein Typ definiert. – dee

+0

@dee: Danke für die Frage. Ich denke, ITypeInfo ist eine wichtige COM-Schnittstelle https://msdn.microsoft.com/en-us/library/windows/desktop/ms221442(v=vs.85).aspx und ist nicht nur zum Schreiben von Bibliotheken relevant, sondern exportiert auch von IDispatch https://msdn.microsoft.com/en-us/library/windows/desktop/ms221571(v=vs.85).aspx Javascript ist dynamisch und daher würde es Sinn machen, nicht so viel in eine statische Typbibliothek zu platzieren als Mitglieder eines Objekts werden "on the fly" erstellt. Vielleicht werde ich den Text der Antwort noch einmal durchgehen, aber ich werde die COM-Schnittstellen im Moment noch einmal besuchen und so wird es bald besser sein, eine aktualisierte Antwort zu geben. –

+0

OK, danke! Der Typ 'JScriptTypeInfo' ist ein wenig mysteriös, ich konnte außer dieser Antwort keine vernünftigen Informationen darüber finden. – dee

Verwandte Themen