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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17262751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 15:56:50  来源:igfitidea点击:

How to access a specific element and attribute in xml with vba in excel?

excel-vbaxml-parsingvbaexcel

提问by user2513952

I'm struggling with getting excel to parse through an xml file. I've found a plethora of examples, but none seem to be quite what I am looking for and I can't seem to get past the error "Object variable or With block variable not set"

我正在努力让 excel 解析一个 xml 文件。我找到了大量的例子,但似乎没有一个是我正在寻找的,我似乎无法克服错误“对象变量或块变量未设置”

The xml is well formed and looks like the following:

xml 格式良好,如下所示:

<xml tag>
<PLMXML>
  <WorkflowTemplate name="">
    <argument name="">
    </argument>
  </WorkflowTemplate >
  <WorkflowTemplate name="">

etc.

等等。

I'm trying to use VBA to get to the value of all the Children's names individually and get to the names of the arguments. I've keep getting the error with this code:

我正在尝试使用 VBA 分别获取所有儿童名称的值并获取参数的名称。我一直收到此代码的错误:

Dim xmlDoc As MSXML2.DOMDocument
Dim xmlElement As MSXML2.IXMLDOMElement
Dim xmlNode As MSXML2.IXMLDOMNode
Dim xmlAttribute As MSXML2.IXMLDOMAttribute

Set xmlDoc = New MSXML2.DOMDocument
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 xmlElement = xmlDoc.DocumentElement

Set xmlNode = xmlElement.SelectSingleNode("WorkflowTemplate[0]")


Set xmlAtribute = xmlNode.Attributes.getNamedItem("name")

I'm not clear on how to get to the data in the document using this parser in excel vba. Any help would be greatly appreciated. I currently have Microsoft XML, v6.0 selected in references.

我不清楚如何在 excel vba 中使用此解析器获取文档中的数据。任何帮助将不胜感激。我目前在参考资料中选择了 Microsoft XML, v6.0。

UPDATE

更新

I've been digging more into it and have come up with the following code, though I still get the same error:

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

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

FINAL UPDATE**

最终更新* *

Figured it out. The loading of the file was the issue. For some reason passing it the string from a msg box doesn't work, but passing it from the gui file selector does. Here's the code I ended up using.

弄清楚了。文件的加载是问题。出于某种原因,从 msg 框中传递字符串不起作用,但从 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

Currently the code breaks on the assigning value section, but going through the code the variables are pulling in the correct values and pulling in the xml information correctly.

目前代码在赋值部分中断,但通过代码变量正在拉入正确的值并正确拉入 xml 信息。

采纳答案by ChrisProsser

I think that the final code presented in the question may not always traverse the whole xml document as the xmlChildren variable is overridden during the loop so I think this may just get the first child node and it's first child and so on.

我认为问题中提供的最终代码可能并不总是遍历整个 xml 文档,因为 xmlChildren 变量在循环期间被覆盖,所以我认为这可能只是获取第一个子节点,它是第一个子节点等等。

To traverse the whole document you can call a separate procedure and build in a recursive call so that it will follow each of the child nodes but then return back to the list it was called from when done.

要遍历整个文档,您可以调用一个单独的过程并构建一个递归调用,以便它遵循每个子节点,但在完成后返回到调用它的列表。

Here is a simplified example where I am looking for all instances of a specific xml element, say all carts in an xml doc containing:

这是一个简化的示例,我在其中查找特定 xml 元素的所有实例,例如 xml 文档中的所有购物车,其中包含:

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

The first procedure below is specific for this example i.e. where the tags are named etc, but the other two can be used generically for any xml document (the first is just an example of how they can be used):

下面的第一个过程是特定于这个例子的,即标签的名称等,但其他两个可以一般用于任何 xml 文档(第一个只是如何使用它们的示例):

' 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