如何在此 XML 中向下钻取以仅提取 <InvoiceHeader> 标签下我想要的标签数据?

问题描述 投票:0回答:2

我正在尝试使用 Excel VBA 将 XML 文件导入电子表格。虽然它有效,但当我只想从文件中提取特定标签数据并将每个特定标签中的数据插入我的电子表格中时,我正在导入整个 XML,距离我的活动单元格几行。例如……

ActiveCell = A1
PurchaseOrder  into   A2
InvoiceNumber   into  A3
BuyerCurrency   into  A4





Sub cmdImportDataFromFile()

Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
    Dim myRow As ListRow
    Dim row_number As Integer
    

With fd

    If .Show = True Then
    
        xmlfilename = .SelectedItems(1)
        
        'Process the file
        Dim fDoc As Object
        Set xDoc = CreateObject("MSXML2.DOMDocument")
        xDoc.async = False: xDoc.validateonparse = False
        xDoc.Load (xmlfilename)
        
        'Get Root Node
        Set selInvoice = xDoc.DocumentElement
        
        'row_number = 6
        For Each InvoiceHeader In selInvoice.ChildNodes
        
            Debug.Print "<InvoiceNumber>:" & InvoiceHeader.ChildNodes(0).text
            Debug.Print "<PurchaseOrderNumber>:" & InvoiceHeader.ChildNodes(1).text
            'Debug.Print "<PurchaseOrderNumber>:" & Product.ChildNodes(0).text
            Debug.Print "----------------------"

           ActiveCell(1, 1).Value = invoiceheader.ChildNodes(0).text
            ActiveCell(1, 2).Value = invoiceheader.ChildNodes(1).text
    
        Next InvoiceHeader
    End If
End With
End Sub

Sample XML File

excel xml vba import
2个回答
0
投票

一旦你有了根节点,你可以简单地使用

SelectSingleNode
方法来检索所需的节点...

Debug.Print "<InvoiceNumber>:" & selInvoice.SelectSingleNode("//InvoiceNumber").Text
            
Debug.Print "<PurchaseOrderNumber>:" & selInvoice.SelectSingleNode("//PurchaseOrderNumber").Text

0
投票

在尝试获取单个节点的文本内容时,有几点需要考虑:

  • 由于您的 xml 文件包含名称空间声明,因此您也必须集成它,以便能够直接使用 XPath 表达式寻址节点。

  • 您可能混淆了单张发票下的从属级别;所需节点的顺序实际上是:

    Invoices/Invoice/Header/InvoiceHeader/...

  • 此外,您应该通过

    CreateObject("MSXML2.DOMDocument.6.0"
    引用最新的xml版本(使用后期绑定符合您的帖子)。

调用示例

'1) Get File name
' ... 
' xmlfilename = ... 

'2) Set xml document to memory in its latest version 6.0 (late binding)
    Dim xDoc As Object: Set xDoc = CreateObject("MSXML2.DOMDocument.6.0")
'3) Add namespace
    xDoc.SetProperty "SelectionNamespaces", _
    "xmlns:n='http://www.xxxxxx.com'"                                   ' note the udf n-prefix
'4) Load xml file
    If xDoc.Load(xmlfilename) Then
        Dim invoice As Object, invoices As Object
        'a) addressing Invoice indirectly (being the next hierarchy level under DocumentElement)
        Set invoices = xDoc.DocumentElement.ChildNodes
        'b) addressing Invoice directly using namespace prefix n:
        ''  Set invoices = xDoc.DocumentElement.SelectNodes("//n:Invoice")

        For Each invoice In invoices
            ' assuming actual text content in wanted nodes
            ' (otherwise dim tmp as object, set tmp = ... and recheck via If Not tmp Is Nothing then ...)
            Debug.Print String(29, "-")
            Debug.Print "InvoiceNumber:       " & invoice.SelectSingleNode("n:*/n:*/n:InvoiceNumber").Text
            Debug.Print "PurchaseOrderNumber: " & invoice.SelectSingleNode("n:*/n:*/n:PurchaseOrderNumber").Text
        Next
    End If

示例文件(例如 invoices.xml)

出于测试目的,您可能需要将以下 xml 文件内容复制到您的硬盘:

<?xml version="1.0" encoding="utf-8"?>
<Invoices xmlns="http://www.xxxxxx.com">
  <Invoice>
    <PaymentTerms>
    </PaymentTerms>
    <Header>
      <InvoiceHeader>
        <InvoiceNumber>3000380</InvoiceNumber>
        <PurchaseOrderNumber>96428312</PurchaseOrderNumber>
      </InvoiceHeader>
      <PaymentTerms>
      </PaymentTerms>
    </Header>
    <Data>
    </Data>
  </Invoice>
  <Invoice>
    <Header>
      <InvoiceHeader>
        <InvoiceNumber>3000381</InvoiceNumber>
        <PurchaseOrderNumber>96428313</PurchaseOrderNumber>
      </InvoiceHeader>
    </Header>
    <Data>
    </Data>
  </Invoice>
</Invoices>

立即窗口输出:

-----------------------------
InvoiceNumber:       3000380
PurchaseOrderNumber: 96428312
-----------------------------
InvoiceNumber:       3000381
PurchaseOrderNumber: 96428313
© www.soinside.com 2019 - 2024. All rights reserved.