在VBA中捕获MSXML2.DOMDocument的onreadystatechange时出错

时间:2013-03-13 15:05:34

标签: vba asynchronous msxml

我在尝试使用包装器类在VBA中安排异步加载和解析XML文档时遇到错误。

遵循this msdn articlethis tutorial中描述的完全用于异步处理MSXML2.XMLHTTP40.send方法的想法,我尝试为DOMDocument.loadXML做类似的事情。

以下是包装类DOMMonitor

中的代码
Private domDoc As MSXML2.DOMDocument
Public Event onXmlLoadComplete(d As MSXML2.DOMDocument)

Public Sub loadXML(XmlFilePath As String)
    Set domDoc = CreateObject("MSXML2.DOMDocument")
    domDoc.async = True
    domDoc.onreadystatechange = Me ' error occurs here
    domDoc.Load XmlFilePath
End Sub

Public Sub onLoadComplete()
    If domDoc.readyState = "4" Then
        RaiseEvent onXmlLoadComplete(domDoc)
    End If
End Sub

我通过设置VB_UserMemId = 0使onLoadComplete成为默认方法,因此应该在domDoc触发onreadystatechange时调用它。

但是当我调用loadXML

Dim dm As DomMonitor
Set dm = New DomMonitor
dm.loadXML txtXMLData

我在此行中收到以下运行时错误:

domDoc.onreadystatechange = Me

此对象无法接收'onreadystatechange'事件。编组对象的IDispatch接口时发生错误

我做错了什么,这里有一个好的解决方法吗?

提前致谢。

P.S。我重新发布该事件的原因是我不一定要为此目的使用最终订户的默认方法。然而,就目前情况而言,我甚至没有达到那个阶段。

2 个答案:

答案 0 :(得分:3)

我读到msdn文章的方式是将包装类分配给readystatechange,该对象必须是IXMLHTTPRequest或IServerXMLHTTPRequest对象(项目符号3)。由于您的对象是DOMDocument,因此readystatechange不接受对象。

但是,我猜你可以实例化一个DOMDocument WithEvents(项目符号2),另一方面是多余的。我没有足够大的xml文件来测试,但我认为这应该有效。我假设如果该类失去了范围,所有的赌注都会关闭,所以我把它变成了一个全局变量。

在标准模块中

Public clsDOMMonitor As CDOMMonitor

Sub test()

    Set clsDOMMonitor = New CDOMMonitor
    clsDOMMonitor.loadXML "C:\Users\dkusleika\Downloads\wurfl-2.3.xml"

End Sub

在CDOMMonitor类中

Private WithEvents mDoc As MSXML2.DOMDocument

Private Sub mDoc_onreadystatechange()

    If mDoc.readyState = 4 Then
        MsgBox "second"
    End If

End Sub

Public Sub loadXML(XmlFilePath As String)

    Set mDoc = New MSXML2.DOMDocument
    mDoc.async = True
    mDoc.Load XmlFilePath

    MsgBox "first"

End Sub

我认为将async设置为True是正常工作所需的全部内容。我的100k xml文件可能做得太快,以至于事件永远不会放弃控制。但是如果你有一个足够大的xml文件,我想你会在“第二个”之前得到“第一个”。

答案 1 :(得分:0)

在延迟绑定时将类的Instancing属性从Private更改为PublicNotCreatable,同时还应用您提到的调整。

在早期绑定时使用上面的示例(如您的情况)。