如何使用excel中的vba访问xml中的特定元素和属性?

如何使用excel中的vba访问xml中的特定元素和属性?,excel,xml-parsing,vba,Excel,Xml Parsing,Vba,我正在努力让excel解析xml文件。我已经找到了大量的例子,但是没有一个是我想要的,而且我似乎无法克服错误“objectvariable或With block variable not set” xml格式良好,如下所示: <xml tag> <PLMXML> <WorkflowTemplate name=""> <argument name=""> </argument> </WorkflowTempl

我正在努力让excel解析xml文件。我已经找到了大量的例子,但是没有一个是我想要的,而且我似乎无法克服错误“objectvariable或With block variable not set”

xml格式良好,如下所示:

<xml tag>
<PLMXML>
  <WorkflowTemplate name="">
    <argument name="">
    </argument>
  </WorkflowTemplate >
  <WorkflowTemplate name="">
我不清楚如何在excel vba中使用此解析器获取文档中的数据。任何帮助都将不胜感激。我目前在参考资料中选择了Microsoft XML v6.0

更新

我一直在深入研究它,并提出了以下代码,尽管我仍然得到相同的错误:

Dim xmlDoc As MSXML2.DOMDocument60
Dim xmlRoot As MSXML2.IXMLDOMNode
Dim xmlTemplate As MSXML2.IXMLDOMNode
Dim xmlAttributes As MSXML2.IXMLDOMNamedNodeMap
Dim xmlName As MSXML2.IXMLDOMNode
Dim xmlChildren As MSXML2.IXMLDOMNodeList
Dim xmlChild As MSXML2.IXMLDOMNode
Dim intI As Long
intI = 1

Set xmlDoc = New MSXML2.DOMDocument60
xmlDoc.async = False
xmlDoc.validateOnParse = False

'ENTER THE PATH WHERE THE XML Workflow DOCUMENT IS STORED:
Dim DocumentPath As String
DocumentPath = InputBox("Enter the full path for the xml workflow document, example: C:\workflows\workflowseasy.xml", "Workflow XML File path", "C:\workflows\workflowseasy.xml")
xmlDoc.Load (DocumentPath)

Set xmlRoot = xmlDoc.DocumentElement *****these say they are empty when debugging
Set xmlChildren = xmlRoot.ChildNodes *****these say they are empty when debugging
For Each xmlTemplate In xmlChildren  *****error occures here
    If xmlTemplate.nodeName = "WorkflowTemplate" Then
    Set xmlAttributes = xmlTemplate.Attributes
    Set xmlName = xmlAttributes.getNamedItem("name")
    ActiveSheet.Cells(int1, 1).Value = xmlName.Text
    Set xmlChildren = xmlTemplate.ChildNodes
    intI = intI + 1
    End If
Next xmlTemplate
最终更新**

我明白了。文件的加载是个问题。出于某种原因,从消息框传递字符串不起作用,但从gui文件选择器传递字符串起作用。这是我最后使用的代码

    Dim xmlDoc As MSXML2.DOMDocument60
Dim xmlRoot As MSXML2.IXMLDOMNode
Dim xmlTemplate As MSXML2.IXMLDOMNode
Dim xmlAttributes As MSXML2.IXMLDOMNamedNodeMap
Dim xmlName As MSXML2.IXMLDOMNode
Dim xmlChildren As MSXML2.IXMLDOMNodeList
Dim xmlChild As MSXML2.IXMLDOMNode
Dim intI As Long
intI = 1

Set xmlDoc = New MSXML2.DOMDocument60
xmlDoc.async = False
xmlDoc.validateOnParse = False

'ENTER THE PATH WHERE THE XML Workflow DOCUMENT IS STORED:
Dim DocumentPath As String
With Application.FileDialog(msoFileDialogOpen)
.Title = "Choose File"
.AllowMultiSelect = False
.Show
'DocumentPath.Show
DocumentPath = .SelectedItems(1)
End With

xmlDoc.Load (DocumentPath)

Set xmlRoot = xmlDoc.DocumentElement
Set xmlChildren = xmlRoot.ChildNodes
For Each xmlTemplate In xmlChildren
    If xmlTemplate.nodeName = "WorkflowTemplate" Then
    Set xmlAttributes = xmlTemplate.Attributes
    Set xmlName = xmlAttributes.getNamedItem("name")
    ActiveSheet.Cells(int1, 1).Value = xmlName.Text
    Set xmlChildren = xmlTemplate.ChildNodes
    intI = intI + 1
    End If
Next xmlTemplate

当前代码在赋值部分中断,但是在代码中,变量正在正确地引入正确的值并正确地引入xml信息。

我认为问题中给出的最终代码可能并不总是遍历整个xml文档,因为xmlChildren变量在循环过程中被重写,所以我想这可能只会得到第一个子节点,它是第一个孩子等等

要遍历整个文档,您可以调用一个单独的过程并构建一个递归调用,这样它将跟随每个子节点,但在完成后返回到从中调用它的列表

下面是一个简化的示例,我在其中查找特定xml元素的所有实例,比如xml文档中包含以下内容的所有carts:

<?xml version="1.0" encoding="UTF-8"?>
<ImportConfig>
    <ShoppingCarts description="Any carts added here will be picked up by the auto import">
        <cart>shopping cart 1 name here</cart>
        <cart>shopping cart 2 name here</cart>
    </ShoppingCarts>
</ImportConfig>

你在哪一行得到错误?当我到达设置xmlNode=xmlement时,它失败。选择SingleNode。我尝试使用它来查看是否至少可以到达值,但这似乎没有给我任何信息。跳过for循环,在xmlList Debug.Print xmlNode.Text Next xmlNode中为每个xmlNode完全设置xmlList=xmlDoc.SELECTNOTES(//WorkflowTemplate))。我已经对这个问题做了更多的研究,我大部分都理解XPath,我不太理解DOMDocument元素或如何使用它们。如果我试图获取xml标记属性的名称,我不知道如何在那里导航。我是否使用IXMLDOMNodeList,然后尝试查看列表中的一项?我可以直接用WorkflowTemplate[1][@name]之类的东西查看第一个工作流模板上的name属性的值并获取它的值吗?我只做过一两次这种编码。这让人困惑,但我最终还是迷茫了。不幸的是,我不知道你问题的答案。祝你好运
<?xml version="1.0" encoding="UTF-8"?>
<ImportConfig>
    <ShoppingCarts description="Any carts added here will be picked up by the auto import">
        <cart>shopping cart 1 name here</cart>
        <cart>shopping cart 2 name here</cart>
    </ShoppingCarts>
</ImportConfig>
' Chris Prosser 09/07/2014
' example use of getElementList (in this case to get all cart elements)

Sub getCarts()
    Dim carts As Collection
    Dim i As Integer

    Set carts = New Collection
    getElementList "C:\Users\Chris\Dropbox\VBAutomation\AutoImportConfig.xml", "cart", carts

    For i = 1 To carts.count
        Debug.Print carts.Item(i)
    Next

End Sub

' Chris Prosser 09/07/2014
' Gets the values of all instances of a specific element from an xml file

Sub getElementList(xml_file_path As String, _
                          elementName As String, _
                          elementValuesList As Collection)

    Dim xmlDoc As MSXML2.DOMDocument
    Dim xmlRoot As MSXML2.IXMLDOMNode
    Dim xmlChildren As MSXML2.IXMLDOMNodeList
    Dim xmlElement As MSXML2.IXMLDOMElement

    Set xmlDoc = New MSXML2.DOMDocument
    xmlDoc.async = False
    xmlDoc.validateOnParse = False
    xmlDoc.Load (xml_file_path)
    Set xmlRoot = xmlDoc.documentElement
    Set xmlChildren = xmlRoot.childNodes

    iterateOverChildNodes xmlChildren, elementName, elementValuesList

End Sub

' Chris Prosser 09/07/2014
' Call with a list of xmlNodes (can be generated from a file using getElementList)
' and an element name to search for. The procedure find child nodes and re-runs
' recursively until all branchs from the list of nodes passed in have been traversed

Sub iterateOverChildNodes(xmlChildren As MSXML2.IXMLDOMNodeList, _
                          elementName As String, _
                          elementValuesList As Collection)

    Dim xmlElement As MSXML2.IXMLDOMElement
    Dim xmlGrandChildren As MSXML2.IXMLDOMNodeList

    For Each xmlElement In xmlChildren
        If xmlElement.nodeName = elementName Then
            'Debug.Print xmlElement.nodeTypedValue
            elementValuesList.Add xmlElement.nodeTypedValue
        Else
            Set xmlGrandChildren = xmlElement.childNodes
            iterateOverChildNodes xmlGrandChildren, elementName, elementValuesList
        End If
    Next xmlElement

End Sub