【问题标题】:Parse Data in XML Document to Excel Worksheet将 XML 文档中的数据解析为 Excel 工作表
【发布时间】:2012-10-04 17:50:37
【问题描述】:
<?xml version="1.0" encoding="UTF-8"?>
<xa:MeContext id="ABCe0552553">
  <xa:Data id="ABCe05525531" />
  <xa:Data id="1" />
  <CustID>Cust1234</CustID>
  <Name>Smith</Name>
  <City>New York</City>
  <Orders>
    <order Orderid="101">
      <Product>MP3 Player</Product>
    </order>
    <order Orderid="102">
      <Product>Radio</Product>
    </order>
  </Orders>
</xa:MeContext>

这个格式良好的 XML 文档使用 MS VBA 代码提供给 Excel 2007。我成功了 使用DOMDocumentIXMLDOMElement 导入名称、城市和产品。
但是,xa:MeContext idvsData1 idVsData2 idCustIDorder Orderid 数字不会导出到 Excel 工作表。

每个 Excel 行都有以下标题,其中包含从 XML 文档填充的数据:

MeContextID--vsData1--VsData2--CustID--Name--City--OrderID--Product--OrderID--Product

【问题讨论】:

  • XML 格式不正确。 &lt;Data&gt; 两个节点都没有结束标记。应该是:&lt;xa:Data id="ABCe05525531" /&gt;
  • 另外,我假设&lt;MeContext&gt; 上的命名空间是错字,但开始标签有xa,结束标签有xn
  • 你是对的。为了清楚起见,我删除了结束标签。如果您能提供帮助,请告诉我。
  • 根据您的评论,我已经编辑了您的 XML,使其格式正确。您为清楚起见删除了结束标签这一事实让我有些困惑,所以如果我将结束标签放在错误的位置,请自行编辑问题。
  • 下一步是要求您显示一些代码...您如何将数据读入 Excel。

标签: xml vba excel


【解决方案1】:

以下是输出所需字段的两种方法。请注意,您发布的 XML 不包含命名空间“xa:”的标头定义,因此不是完全形成的 XML。我在示例中删除了它们,因此 MSXML2.DOMDocument 不会引发解析错误。

Option Explicit
Sub XMLMethod()
Dim XMLString As String
Dim XMLDoc As Object
Dim boolValue As Boolean
Dim xmlDocEl As Object
Dim xMeContext As Object
Dim xChild As Object
Dim xorder As Object


    XMLString = Sheet1.Range("A1").Value

    'Remove xa: in this example
    'reason : "Reference to undeclared namespace prefix: 'xa'."
    'Shouldn't need to do this if full XML is well formed containing correct namespace
    XMLString = Replace(XMLString, "xa:", vbNullString)

    Set XMLDoc = CreateObject("MSXML2.DOMDocument")
    'XMLDoc.setProperty "SelectionNamespaces", "xa:"

        'XMLDoc.Load = "C:\Users\ooo\Desktop\test.xml" 'load from file
    boolValue = XMLDoc.LoadXML(XMLString)  'load from string

    Set xmlDocEl = XMLDoc.DocumentElement
    Set xMeContext = xmlDocEl.SelectSingleNode("//MeContext")
        Debug.Print Split(xMeContext.XML, """")(1)
    For Each xChild In xmlDocEl.ChildNodes

        If xChild.NodeName = "Orders" Then
            For Each xorder In xChild.ChildNodes
                Debug.Print Split(xorder.XML, """")(1)
                Debug.Print xorder.Text
            Next xorder

        ElseIf xChild.Text = "" Then
            Debug.Print Split(xChild.XML, """")(1)
        Else
            Debug.Print xChild.Text
        End If


    Next xChild

    'Output:
    'ABCe0552553
    'ABCe05525531
    '1
    'Cust1234
    'Smith
    'New York
    '101
    'MP3 Player
    '102
    'Radio


End Sub

以下使用正则表达式,这仅在每次将 XML 都固定为您的示例时才真正有用。除非您希望速度超过可靠性,否则通常不建议将它用于解析 XML。

Option Explicit

Sub RegexMethod()
Dim XMLString As String
Dim oRegex As Object
Dim regexArr As Object
Dim rItem As Object

    'Assumes Sheet1.Range("A1").Value holds example XMLString
    XMLString = Sheet1.Range("A1").Value

    Set oRegex = CreateObject("vbscript.regexp")
    With oRegex
        .Global = True
        .Pattern = "(id=""|>)(.+?)(""|</)"
        Set regexArr = .Execute(XMLString)

        'No lookbehind so replace unwanted chars
        .Pattern = "(id=""|>|""|</)"
        For Each rItem In regexArr
            'Change Debug.Print to fill an array to write to Excel
            Debug.Print .Replace(rItem, vbNullString)
        Next rItem
    End With

    'Output:
    'ABCe0552553
    'ABCe05525531
    '1
    'Cust1234
    'Smith
    'New York
    '101
    'MP3 Player
    '102
    'Radio


End Sub

编辑:稍微更新输出到数组以写入范围

Option Explicit

Sub RegexMethod()
Dim XMLString As String
Dim oRegex As Object
Dim regexArr As Object
Dim rItem As Object
Dim writeArray(1 To 1, 1 To 10) As Variant
Dim col As Long

    'Assumes Sheet1.Range("A1").Value holds example XMLString
    XMLString = Sheet1.Range("A1").Value

    Set oRegex = CreateObject("vbscript.regexp")
    With oRegex
        .Global = True
        .Pattern = "(id=""|>)(.+?)(""|</)"
        Set regexArr = .Execute(XMLString)

        'No lookbehind so replace unwanted chars
        .Pattern = "(id=""|>|""|</)"
        For Each rItem In regexArr
            'Change Debug.Print to fill an array to write to Excel
            Debug.Print .Replace(rItem, vbNullString)

            col = col + 1
            writeArray(1, col) = .Replace(rItem, vbNullString)
        Next rItem
    End With

    Sheet1.Range("A5:J5").Value = writeArray


End Sub


Sub XMLMethod()
Dim XMLString As String
Dim XMLDoc As Object
Dim boolValue As Boolean
Dim xmlDocEl As Object
Dim xMeContext As Object
Dim xChild As Object
Dim xorder As Object
Dim writeArray(1 To 1, 1 To 10) As Variant
Dim col As Long


    XMLString = Sheet1.Range("A1").Value

    'Remove xa: in this example
    'reason : "Reference to undeclared namespace prefix: 'xa'."
    'Shouldn't need to do this if full XML is well formed
    XMLString = Replace(XMLString, "xa:", vbNullString)

    Set XMLDoc = CreateObject("MSXML2.DOMDocument")
    'XMLDoc.setProperty "SelectionNamespaces", "xa:"

        'XMLDoc.Load = "C:\Users\ooo\Desktop\test.xml" 'load from file
    boolValue = XMLDoc.LoadXML(XMLString)  'load from string

    Set xmlDocEl = XMLDoc.DocumentElement
    Set xMeContext = xmlDocEl.SelectSingleNode("//MeContext")
        'Debug.Print Split(xMeContext.XML, """")(1)
        col = col + 1
        writeArray(1, col) = Split(xMeContext.XML, """")(1)
    For Each xChild In xmlDocEl.ChildNodes

        If xChild.NodeName = "Orders" Then
            For Each xorder In xChild.ChildNodes
                col = col + 1
                'Debug.Print Split(xorder.XML, """")(1)
                writeArray(1, col) = Split(xorder.XML, """")(1)
                col = col + 1
                'Debug.Print xorder.Text
                writeArray(1, col) = xorder.Text
            Next xorder
        ElseIf xChild.Text = "" Then
            col = col + 1
            'Debug.Print Split(xChild.XML, """")(1)
            writeArray(1, col) = Split(xChild.XML, """")(1)
        Else
            col = col + 1
            'debug.Print xChild.Text
            writeArray(1, col) = xChild.Text
        End If


    Next xChild

    Sheet1.Range("A5:J5").Value = writeArray


End Sub

【讨论】:

  • 感谢您花时间编写两个代码示例。您正在以垂直方式显示每个 XML 记录的输出(每个输出一个 Excel 行)。是否可以以水平方式输出(将输出显示为列而不是行)?
  • 我已经更新了我的答案,展示了一种将数据转储到数组中以写入工作表的粗略方法。
猜你喜欢
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 2021-04-23
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多