如何用VBA解析XML问题,怎么解决
XML也是储存数据的一种常用形式,这节来看下从XML文件中取数据的一般方法。
一般来说,如果你的XML文件结构比较规整的话可以用Excel自带的功能来直接导入XML形式的文件,在开发工具菜单XML组中找导入,非常方便,今天我们主要来看怎样用VBA来处理XML文件。
现在我手上有一个名为Rawdata.xml的XML文件,现在我想要把该文件中所有的数据都取到Excel中,直接看代码
Private Sub OpenXml1()
Dim objDOM, n, nodes As Object, ns, i, j
Set objDOM = CreateObject("MSXML.DOMDocument")
objDOM.Load (ThisWorkbook.Path & "\Rawdata.xml")
objDOM.async = False
Set ns = objDOM.SelectNodes("//extraction") '取节点extraction,即行
Set n = objDOM.SelectSingleNode("//extraction") '取单个Extraction,其长度即列
For i = 1 To ns.Length
For j = 1 To n.ChildNodes.Length
Cells(i, j) = ns.Item(i - 1).ChildNodes(j - 1).Text
Next
Next
Debug.Print n.ChildNodes.Length
Debug.Print ns.Length
Debug.Print ns.Item(0).Text
Set objDOM = Nothing
End Sub
代码稍微解释一下,先建立一个DOM对象,然后用Load方法将XML文件内容载入。选取节点用的是SelectNodes,该XML文件中行标签是extraction,所以我选择了该节点,那节点的个数就是行数了。获得单个节点的结构用的是SelectSingleNode,那这单个节点中子节点的个数n.ChildNodes.Length就是列数了。ns.Item(i).ChildNodes(j).text就是节点集ns中第i项的第j个子节点的值,我们要的内容也就取出来了。
那如果我不要取所有的列,只想取某几列,那怎么办,看代码
Private Sub OpenXml2()
Dim objDOM, n, ns, i, j, strh(), arr()
Cells.Clear
strh = Array("tdx", "tda", "tdb", "tdc", "tdk", "tdl", "tdy", "tdm", "tdn", "tdo", "tdp", "tdq", "tdu", "tdv", "td1", "new1", "new2")
Set objDOM = CreateObject("MSXML.DOMDocument")
objDOM.Load (ThisWorkbook.Path & "\Rawdata.xml")
objDOM.async = False
'MsgBox objDOM.XML
Set ns = objDOM.SelectNodes("//extraction")
Set n = objDOM.SelectSingleNode("//extraction")
ReDim arr(1 To ns.Length, 1 To UBound(strh) + 1)
For i = 1 To ns.Length
For j = 1 To UBound(strh) + 1
On Error Resume Next
arr(i, j) = ns.Item(i - 1).GetElementsByTagname(strh(j - 1)).Item(0).Text
Next
Next
Set ns = Nothing
Set n = Nothing
Set objDOM = Nothing
Range("A1").Resize(UBound(arr), UBound(strh) + 1) = arr
End Sub
上面的代码就是取以"tdx", "tda", "tdb", "tdc", "tdk", "tdl", "tdy", "tdm", "tdn", "tdo", "tdp", "tdq", "tdu", "tdv", "td1", "new1", "new2"为标签的列,和前面不同的主要是这句ns.Item(i - 1).GetElementsByTagname(strh(j - 1)).Item(0).Text,用getelementsbytagname(节点名)取节点,ns.Item(i-1)是行节点的第n-1项,从这项中用GetElementsByTagname取出相应的列节点,一般来说到列了不会有多项了,所以我们直接用第1项(下标是0)的值来表示我们要的结果,之间的层层关系自己体会一下。