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

在Windows Excel VBA中,如何获取JSON密钥以抢占“运行时错误'438':对象不支持此属性或方法”?

慕容雅珺
2023-03-14
问题内容

在这里回答我自己的问题。
我已经在Excel VBA中使用JSON完成了一些工作,并发布了很多发现,并将以问答格式
http://blog.stackoverflow.com/2011发布/ 07
/它可以询问并回答您自己的问题/

因此,在stackoverflow上的其他地方,可以看到有关在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]”?我介绍了一些调试“糖”,它可以很好地检查变量。

在此问题中,我问我们如何以编程方式获取可以检测到密钥存在的成员列表,这将有助于抢占任何“运行时错误‘438”:对象不支持此属性或方法错误并允许我们编写防御性(希望是“防弹”的)代码?


问题答案:

与使用已解析的JSON对象相关的其他堆栈溢出问题的答案使用小型脚本方法,我们可以在此处使用此方法。如果说我们正在运行Microsoft
Windows版本的Excel VBA,则可以使用库中的脚本字典Microsoft Scripting Runtime

我们可以在Javascript中创建Scripting.Dictionary,使用JSON对象的键填充它,还可以使用这些值作为对子元素的引用,最后传递回VBA。在VBA中,然后可以使用Dictionary的Exists方法防御丢失的密钥。可以使用Dictionary的Count方法确定其他下游变量的尺寸。甚至可以使用Dictionary的Item方法来检索子元素(仅向下一级)。

从而,

'Tools->References->
'Microsoft Scripting Runtime
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

Option Explicit

Private Function GetScriptEngine() As ScriptControl
    Static soScriptEngine As ScriptControl
    If soScriptEngine Is Nothing Then
        Set soScriptEngine = New ScriptControl
        soScriptEngine.Language = "JScript"

        soScriptEngine.AddCode "function getKeyValues(jsonObj) { " & _
                              " var dictionary = new ActiveXObject(""Scripting.Dictionary""); " & _
                              " var keys = new Array(); for (var i in jsonObj) { dictionary.add(i,jsonObj[i]); }; return dictionary; } "


    End If
    Set GetScriptEngine = soScriptEngine
End Function


Private Sub TestJSONParsingWithCallByName3()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = GetScriptEngine

    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"

    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")

    Dim dicKeys As Scripting.Dictionary
    Set dicKeys = oScriptEngine.Run("getKeyValues", objJSON)

    Debug.Assert dicKeys.Count = 2

    Debug.Assert TypeName(dicKeys.Item(dicKeys.Keys()(1))) = "JScriptTypeInfo"
    Stop

    If dicKeys.Exists("foobarbaz") Then

        '*** Next line WOULD throw "Run-time error '438': Object doesn't support this property or method" because "foobarbaz" is not a key
        '*** but is skipped because of defensive code.
        Debug.Assert VBA.CallByName(objJSON, "foobarbaz", VbGet)

    End If

End Sub

但是,我还发现了一个不需要miniscript或Scripting.Dictionary的奇妙替代方法。它将允许抢占丢失的键,但没有集合类功能。它使用了hasOwnProperty()鲜为人知的属性。从而,

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

Option Explicit

Private Sub TestJSONParsingWithCallByName4()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"

    Dim objJSON As Object
    Set objJSON = oScriptEngine.Eval("(" + sJsonString + ")")

    Debug.Assert objJSON.hasOwnProperty("key1")
    Debug.Assert objJSON.hasOwnProperty("key2")

    Dim objKey2 As Object
    Set objKey2 = VBA.CallByName(objJSON, "key2", VbGet)

    Debug.Assert objKey2.hasOwnProperty("key3")


    If objJSON.hasOwnProperty("foobarbaz") Then

        '*** Next line WOULD throw "Run-time error '438': Object doesn't support this property or method" because "foobarbaz" is not a key
        '*** but is skipped because of defensive code.
        Debug.Assert VBA.CallByName(objJSON, "foobarbaz", VbGet)

    End If

End Sub


 类似资料:
  • 好吧,我在VBA肯定是个新手,但我正在学习。据我所知,我的代码没有理由不能正常运行,过去也是如此。尽管这个错误不断出现。我的目的是制作一个工作表,当你在主工作表中添加一个人时,它会自动更新其他工作表。代码看起来工作正常,但是它突然抛出这个错误,我不知道为什么。我四处看了看,但似乎没有一个解决方案与我的问题有丝毫关联。任何有助于找出错误所在的帮助都将不胜感激! 以下是调试器指出错误的位置: 这是正在

  • 我有一个工作表,用于组织,样式化和汇总数据,然后复制自身并将另一个副本保存为.PDF。 在原始工作表上,有3个由形状组组成的“按钮”,用于运行不同的宏(“重置”、“修复丢失的员工”、“打印和电子邮件摘要”)。问题是在副本中删除它们。这是从录制的宏: 我想选择/删除所有形状。我不能使用“shapes.select”、“shapes.delete”或我找到的任何帮助。除了上面列出的代码之外,每一次尝试

  • 我需要简单地计算一张纸上的区域数。我的密码是: 但是由于某种原因,我收到错误消息“Object 不支持此属性或方法。”我不知道为什么。这段代码基本上只是从微软网站复制的。 我甚至无法使用即时窗口打印部分。 有什么快速的帮助吗?我正在使用Excel 2010。 谢了。

  • 我有以下rails配置: 有没有人对是什么导致了这个错误有什么建议?

  • 我是VB代码的新手,我正在尝试执行下面的代码。但是我收到一条错误消息,此行对象不支持此属性或方法 我认为我的代码没有读取< code>ReceivedTime。我正在使用微软Excel 2010。我如何修理它?

  • 问题内容: 我在Surface Pro 3上安装了Rails,并在尝试查看页面后遇到此错误。我尝试了一些建议,例如使用libv8安装rubyracer,但没有帮助。 TypeError:对象不支持此属性或方法(在c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/turbolinks-2.5.3/lib/assets/javascripts/t