当前位置: 首页 > 面试题库 >

在Windows上的Excel VBA中,对于已解析的JSON变量,此JScriptTypeInfo到底是什么?

束研
2023-03-14
问题内容

可以看到有关在VBA中解析JSON的问题,但它们似乎错过了一两个技巧。

首先,我不再使用自定义JSON解析库,而是使用ScriptControl的Eval方法作为所有JSON代码的基础。另外,我们对本机Microsoft解决方案表示偏爱。

这是一个先前的问题,在Windows上的Excel
VBA中,如何减轻IDE的大写行为破坏解析的JSON的点语法遍历的问题?这个问题基于此。它显示了与使用点语法遍历已解析的JSON对象相比,使用VBA.CallByName的鲁棒性更高。还有另一个先前的问题,在Windows上的ExcelVBA中,如何遍历解析的JSON数组?显示了如何将其也用于访问数组元素。但是CallByName返回一个奇怪的变量类型,它在监视窗口中显示为Object/JScriptTypeInfo,并且如果一种类型的Debug.Print在当前窗口中(或将鼠标悬停在变量上)将获得无意义的“ [objectObject]”。在系列的另一个问题中[在Windows上的Excel VBA中,如何为解析的JSON变量获取字符串化的JSON表示形式而不是“object Object]”?我介绍了一些调试“糖”,它可以很好地检查变量。第四个问题,在Windows Excel
VBA中,如何获取JSON密钥以抢占“运行时错误‘438’:对象不支持此属性或方法”?,在研究如何查询成员的JSON对象时,我发现了似乎附加在JScriptTypeInfo对象上的hasOwnProperty()方法。

所以我问这个问题,这个JScriptTypeInfo到底是什么?


问题答案:

一个可能的地方是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(Java脚本的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)的一种方法,该方法是处理VBA对象声明为Object类型的(例如Dim foo as Object)必需的。使用regsvr32注册类型库似乎无济于事。必须在“工具参考”中浏览该文件才能在VBA的对象浏览器中查看。

我们可以很确定地知道这个JScript.dll文件,因为使用Process Explorer我们可以看到执行该行时正在加载dll
oScriptEngine.Language = "JScript" 。在缺少注册类型库的情况下,我将文件JScript.dll加载到了Notepad
++中,并搜索了.JScriptTypeInfo作为正则表达式,发现一击。答对了!

不仅有一个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是要在VBAIDE监视窗口中显示的内容以及VBA函数TypeName()的返回,但是它实际上隐藏了可以在JScript.dll中找到的许多对象。我想可以将其描述为多态的,也许最好将其描述为后期绑定。要查看功能,请使用“工具参考”并浏览到JScript.dll。



 类似资料:
  • null 例如,我在清单中定义了两个变量: 当调试角色中这些变量的类型时······ ...然后变成,但是被解释为: 我不得不在执行生产剧本后艰难地意识到这一点,运行一些不应该运行的东西,因为在库存中变量设置为“false”而不是“false”。因此,我真的很想找到一个明确的答案,关于Ansible如何理解布尔值,以及它如何依赖于变量的定义位置/方式。为了保险起见,我应该简单地总是使用大写的tru

  • 本文向大家介绍详解javascript中的babel到底是什么,包括了详解javascript中的babel到底是什么的使用技巧和注意事项,需要的朋友参考一下 javascript在不断的发展,各种新的标准和提案层出不穷,但是由于浏览器的多样性,导致可能几年之内都无法广泛普及,babel可以让你提前使用这些语言特性,他是一种用途很多的javascript编译器,他把最新版的javascript编译

  • 我很难将具有可变内容的JSON对象解析为Java对象。 我的JSON如下所示: 通过一个典型的Json到Java对象转换器运行这段代码是不起作用的,因为它不能映射到一个简单的POJO。 我尝试转换为,但不出所料,出现了一个异常: Edit:正如注释中所指出的,提供的JSON数据不是以有效的键值对形式提供的。我已经联系了API提供商,他们会解决这个问题的。 在我找到一个处理这个问题的方法之前,我将保

  • 问题内容: 该消息包含很多示例,时间有点长,但是我希望它能帮助我和其他人更好地掌握Python 2.7中变量和属性查找的全部内容。 我正在将PEP 227(http://www.python.org/dev/peps/pep-0227/)的术语用于代码块(例如模块,类定义,函数定义等)和变量绑定(例如作为赋值,参数声明,类和函数声明,for循环等) 我将术语变量用于可以不带点号调用的名称,将属性用

  • 问题内容: 我想拉出用户块。JSON结果将始终更改,有时将返回4个用户,有时将返回10个,等等。 问题答案: 使用JSONObject

  • 本文向大家介绍Javascript中的Prototype到底是什么,包括了Javascript中的Prototype到底是什么的使用技巧和注意事项,需要的朋友参考一下 Javascript也是面向对象的语言,但它是一种基于原型Prototype的语言,而不是基于类的语言。在Javascript中,类和对象看起来没有太多的区别。 什么是prototype: function定义的对象有一个proto