Чтение xml excel vba

XML files are one of the most common type of data files apart from text and CSV (comma-separated values) files. Reading data files which are not hierarchical (as XML files or JSON) is relatively easy. You can read in the data row by row and process columns separately. With XML (and JSON) the task is not as easy as the data is hierarchical (parent-child relationships exist between records in the schema) and the number of underlying nodes may vary as opposed to tabular data which usually has a constant number of columns separated with a specific delimiter.

Fortunately, we can use the MSXML2.DOMDocument object in VBA. Let’s however, as always, start with a short introduction as to how XML files a structure before we dive into the examples.

Loading XML document in VBA

The MSXML2.DOMDocument object allows you to easily traverse through an XML structure an extract any XML node and/or attribute needed. Let’s look at the example below.

Below we start by loading the XML document. Notice that I am selecting the load to be performed synchronously and not validation be carried out on parsing the document. Feel free to change these options if needed.

Sub TestXML()
    Dim XDoc As Object, root as Object
    
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "test.xml")
    Set root = XDoc.DocumentElement
    '... 
End Sub

Alternatively load an XML from a string:

Sub TestXML()
    Dim XDoc As Object, root as Object
    
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.LoadXML ("<root><child></child></root>")
    Set root = XDoc.DocumentElement
    '... 
End Sub

That’s it. You have loaded the XML document into memory into the DOMDocument object. The document has been parsed and you can easily traverse the enclosed elements. See next section.

XML DOM nodes in VBA

For the below I will use the following examples XML:

<?xml version="1.0" encoding="utf-8"?>
<DistributionLists>
    <List>
        <Name>Recon</Name>
        <TO>John;Bob;Rob;Chris</TO>
        <CC>Jane;Ashley</CC>
        <BCC>Brent</BCC>
    </List>
    <List>
        <Name>Safety Metrics</Name>
        <TO>Tom;Casper</TO>
        <CC>Ashley</CC>
        <BCC>John</BCC>
    </List>
    <List>
        <Name>Performance Report</Name>
        <TO>Huck;Ashley</TO>
        <CC>Tom;Andrew</CC>
        <BCC>John;Seema</BCC>
    </List>
</DistributionLists>

The XML document will provide you with the root of the entire DOM (of type XDoc.DocumentElement). Each DocumentElement (XML DOM node) facilitates the following node references:

Node Reference Type Description
parentNode [XDoc.DocumentElement] The parent node, one node higher in the DOM hierarchy
firstChild [XDoc.DocumentElement] The first child node, first node lower in the DOM hierarchy
lastChild [XDoc.DocumentElement] The last child node, last node lower in the DOM hierarchy
childNodes [Array of type XDoc.DocumentElement] All child nodes of the current node, all nodes lower in the DOM hierarchy
nextSibling [XDoc.DocumentElement] Next sibling node i.e. node on the same level in the DOM hierarchy, having the same parent node
previousSibling [XDoc.DocumentElement] Previous sibling node i.e. node on the same level in the DOM hierarchy, having the same parent node

All the above references allow you to free move within the XML DOM.

ChildNodes

Let’s start by extracting the first list and printing it’s XML and text contents. The basics to moving around the XML DOM is using ChildNodes.

Sub TestXML()
    Dim XDoc As Object
    
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "test.xml")
    
    'Get Document Elements
    Set lists = XDoc.DocumentElement
    
    'Get first child ( same as ChildNodes(0) )
    Set getFirstChild = lists.FirstChild
    'Print first child XML
    Debug.Print getFirstChild.XML
    'Print first child Text
    Debug.Print getFirstChild.Text

    Set XDoc = Nothing
End Sub

This is the result

'Print first child XML
<List>
    <Name>Recon</Name>
    <TO>John;Bob;Rob;Chris</TO>
    <CC>Jane;Ashley</CC>
    <BCC>Brent</BCC>
</List>
'Print first child Text
Recon John;Bob;Rob;Chris Jane;Ashley Brent

Traversing through the whole XML in VBA

Now that we got the basics let’s print out the whole contents of the XML DOM including the basenames (node names).

Sub TestXML()
    Dim XDoc As Object
    
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "test.xml")
    
    'Get Document Elements
    Set lists = XDoc.DocumentElement
    
    'Traverse all elements 2 branches deep
    For Each listNode In lists.ChildNodes
        Debug.Print "---Email---"
        For Each fieldNode In listNode.ChildNodes
            Debug.Print "[" & fieldNode.BaseName & "] = [" & fieldNode.Text & "]"
        Next fieldNode
    Next listNode
    
    Set XDoc = Nothing
End Sub

This is the result:

---Email---
[Name] = [Recon]
[TO] = [John;Bob;Rob;Chris]
[CC] = [Jane;Ashley]
[BCC] = [Brent]
---Email---
[Name] = [Safety Metrics]
[TO] = [Tom;Casper]
[CC] = [Ashley]
[BCC] = [John]
---Email---
[Name] = [Performance Report]
[TO] = [Huck;Ashley]
[CC] = [Tom;Andrew]
[BCC] = [John;Seema]

Easy right? Using the basics above we can easily move around the document. But this still seems like a lot of coding right? Well there is an easier way of moving / extracting items using the DOMDocument object – called XPath.

XML Document example node references

Now that we have a hang of our XML document, based on the example XML I provided above I mapped a reference to how to obtain various elements of our XML file by using node references:

  • DistributionLists [FirstChild]
    • List [ChildNodes(0)]
      • Name: Recon [ChildNodes(0).ChildNodes(0).innerText]
      • TO: John;Bob;Rob;Chris [ChildNodes(0).ChildNodes(1).innerText]
      • CC: Jane;Ashley
      • BCC: Brent
    • (…)

    • List [ChildNodes(1)]
      • Name: Performance Report [ChildNodes(1).ChildNodes(0).innerText]
      • TO: Huck;Ashley
      • CC: Tom;Andrew
      • BCC: John;Seema

XPath in VBA

Instead of traversing the elements/nodes in your XML using the .ChildNodes/.FirstChild/NextChild properties we can also use XPath. XPath is a query language used for selecting XML nodes in an XML document. It is represented by a single string. It allows you to extract any number of nodes (0 or more) which match the specified XPath query.

If you want to learn XPath I can recommend this overview:
https://www.w3schools.com/xml/xpath_syntax.asp

Now let’s jump into an example:

Example 1: Extract all Lists

Sub TestXML()
    Dim XDoc As Object
    
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "test.xml")
    
    Set lists = XDoc.SelectNodes("//DistributionLists/List")

    Set XDoc = Nothing
End Sub

Example 2: Extracting all TO fields

Set toFields = XDoc.SelectNodes("//DistributionLists/List/TO")
End Sub

Example 3: Extracting the first and last Name field

Set firstNameField = XDoc.SelectNodes("//DistributionLists/List[0]/Name")

Set lastNameField = XDoc.SelectNodes("//DistributionLists/List[2]/Name")

Example 3: Extracting all child List nodes (Name, TO, CC, BCC)

Set listChildrenField = XDoc.SelectNodes("//DistributionLists/List/*")

XML Attributes in VBA

Let’s tackle one last example – attributes. Let’s slightly modify the XML above and include an example attribute named attribute.

<?xml version="1.0" encoding="utf-8"?>
<DistributionLists>
    <List>
        <Name attribute="some">Recon</Name>

Using XPath (or traversing the DOM) we can easily extract the attribute as shown below.

Set firstNameField = XDoc.SelectNodes("//DistributionLists/List[0]/Name")
Debug.Print firstNameField(0).Attributes(0).Text
'Result: "some"

Creating XML documents

Creating documents is also quite straight forward in VBA.

Dim XDoc As Object, root As Object, elem As Object
Set XDoc = CreateObject("MSXML2.DOMDocument")
Set root = XDoc.createElement("Root")
XDoc.appendChild root
 
'Add child to root
Set elem = XDoc.createElement("Child")
root.appendChild elem
    
'Add Attribute to the child
Dim rel As Object
Set rel = XDoc.createAttribute("Attrib")
rel.NodeValue = "Attrib value"
elem.setAttributeNode rel
    
'Save the XML file
XDoc.Save "C:my_file.xml"

I work in VBA, and want to parse a string eg

<PointN xsi:type='typens:PointN' 
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
xmlns:xs='http://www.w3.org/2001/XMLSchema'>
    <X>24.365</X>
    <Y>78.63</Y>
</PointN>

and get the X & Y values into two separate integer variables.

I’m a newbie when it comes to XML, since I’m stuck in VB6 and VBA, because of the field I work in.

How do I do this?

Trevor Reid's user avatar

Trevor Reid

3,1824 gold badges27 silver badges46 bronze badges

asked Aug 14, 2008 at 16:41

Devdatta Tengshe's user avatar

Devdatta TengsheDevdatta Tengshe

3,9659 gold badges45 silver badges59 bronze badges

1

Thanks for the pointers.

I don’t know, whether this is the best approach to the problem or not, but here is how I got it to work.
I referenced the Microsoft XML, v2.6 dll in my VBA, and then the following code snippet, gives me the required values

Dim objXML As MSXML2.DOMDocument

Set objXML = New MSXML2.DOMDocument

If Not objXML.loadXML(strXML) Then  'strXML is the string with XML'
    Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason
End If
 
Dim point As IXMLDOMNode
Set point = objXML.firstChild

Debug.Print point.selectSingleNode("X").Text
Debug.Print point.selectSingleNode("Y").Text

bluish's user avatar

bluish

25.9k27 gold badges120 silver badges179 bronze badges

answered Aug 14, 2008 at 17:40

Devdatta Tengshe's user avatar

Devdatta TengsheDevdatta Tengshe

3,9659 gold badges45 silver badges59 bronze badges

1

Add reference Project->References Microsoft XML, 6.0 and you can use example code:

    Dim xml As String

    xml = "<root><person><name>Me </name> </person> <person> <name>No Name </name></person></root> "
    Dim oXml As MSXML2.DOMDocument60
    Set oXml = New MSXML2.DOMDocument60
    oXml.loadXML xml
    Dim oSeqNodes, oSeqNode As IXMLDOMNode

    Set oSeqNodes = oXml.selectNodes("//root/person")
    If oSeqNodes.length = 0 Then
       'show some message
    Else
        For Each oSeqNode In oSeqNodes
             Debug.Print oSeqNode.selectSingleNode("name").Text
        Next
    End If 

be careful with xml node //Root/Person is not same with //root/person, also selectSingleNode(«Name»).text is not same with selectSingleNode(«name»).text

SierraOscar's user avatar

SierraOscar

17.5k6 gold badges41 silver badges68 bronze badges

answered Oct 13, 2015 at 13:29

No Name's user avatar

No NameNo Name

6996 silver badges14 bronze badges

1

You can use a XPath Query:

Dim objDom As Object        '// DOMDocument
Dim xmlStr As String, _
    xPath As String

xmlStr = _
    "<PointN xsi:type='typens:PointN' " & _
    "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " & _
    "xmlns:xs='http://www.w3.org/2001/XMLSchema'> " & _
    "    <X>24.365</X> " & _
    "    <Y>78.63</Y> " & _
    "</PointN>"

Set objDom = CreateObject("Msxml2.DOMDocument.3.0")     '// Using MSXML 3.0

'/* Load XML */
objDom.LoadXML xmlStr

'/*
' * XPath Query
' */        

'/* Get X */
xPath = "/PointN/X"
Debug.Print objDom.SelectSingleNode(xPath).text

'/* Get Y */
xPath = "/PointN/Y"
Debug.Print objDom.SelectSingleNode(xPath).text

SierraOscar's user avatar

SierraOscar

17.5k6 gold badges41 silver badges68 bronze badges

answered Dec 30, 2014 at 11:24

mvanle's user avatar

mvanlemvanle

1,77720 silver badges19 bronze badges

This is an example OPML parser working with FeedDemon opml files:

Sub debugPrintOPML()

' http://msdn.microsoft.com/en-us/library/ms763720(v=VS.85).aspx
' http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectnodes.aspx
' http://msdn.microsoft.com/en-us/library/ms256086(v=VS.85).aspx ' expressions
' References: Microsoft XML

Dim xmldoc As New DOMDocument60
Dim oNodeList As IXMLDOMSelection
Dim oNodeList2 As IXMLDOMSelection
Dim curNode As IXMLDOMNode
Dim n As Long, n2 As Long, x As Long

Dim strXPathQuery As String
Dim attrLength As Byte
Dim FilePath As String

FilePath = "rss.opml"

xmldoc.Load CurrentProject.Path & "" & FilePath

strXPathQuery = "opml/body/outline"
Set oNodeList = xmldoc.selectNodes(strXPathQuery)

For n = 0 To (oNodeList.length - 1)
    Set curNode = oNodeList.Item(n)
    attrLength = curNode.Attributes.length
    If attrLength > 1 Then ' or 2 or 3
        Call processNode(curNode)
    Else
        Call processNode(curNode)
        strXPathQuery = "opml/body/outline[position() = " & n + 1 & "]/outline"
        Set oNodeList2 = xmldoc.selectNodes(strXPathQuery)
        For n2 = 0 To (oNodeList2.length - 1)
            Set curNode = oNodeList2.Item(n2)
            Call processNode(curNode)
        Next
    End If
        Debug.Print "----------------------"
Next

Set xmldoc = Nothing

End Sub

Sub processNode(curNode As IXMLDOMNode)

Dim sAttrName As String
Dim sAttrValue As String
Dim attrLength As Byte
Dim x As Long

attrLength = curNode.Attributes.length

For x = 0 To (attrLength - 1)
    sAttrName = curNode.Attributes.Item(x).nodeName
    sAttrValue = curNode.Attributes.Item(x).nodeValue
    Debug.Print sAttrName & " = " & sAttrValue
Next
    Debug.Print "-----------"

End Sub

This one takes multilevel trees of folders (Awasu, NewzCrawler):

...
Call xmldocOpen4
Call debugPrintOPML4(Null)
...

Dim sText4 As String

Sub debugPrintOPML4(strXPathQuery As Variant)

Dim xmldoc4 As New DOMDocument60
'Dim xmldoc4 As New MSXML2.DOMDocument60 ' ?
Dim oNodeList As IXMLDOMSelection
Dim curNode As IXMLDOMNode
Dim n4 As Long

If IsNull(strXPathQuery) Then strXPathQuery = "opml/body/outline"

' http://msdn.microsoft.com/en-us/library/ms754585(v=VS.85).aspx
xmldoc4.async = False
xmldoc4.loadXML sText4
If (xmldoc4.parseError.errorCode <> 0) Then
   Dim myErr
   Set myErr = xmldoc4.parseError
   MsgBox ("You have error " & myErr.reason)
Else
'   MsgBox xmldoc4.xml
End If

Set oNodeList = xmldoc4.selectNodes(strXPathQuery)

For n4 = 0 To (oNodeList.length - 1)
    Set curNode = oNodeList.Item(n4)
    Call processNode4(strXPathQuery, curNode, n4)
Next

Set xmldoc4 = Nothing

End Sub

Sub processNode4(strXPathQuery As Variant, curNode As IXMLDOMNode, n4 As Long)

Dim sAttrName As String
Dim sAttrValue As String
Dim x As Long

For x = 0 To (curNode.Attributes.length - 1)
    sAttrName = curNode.Attributes.Item(x).nodeName
    sAttrValue = curNode.Attributes.Item(x).nodeValue
    'If sAttrName = "text"
    Debug.Print strXPathQuery & " :: " & sAttrName & " = " & sAttrValue
    'End If
Next
    Debug.Print ""

If curNode.childNodes.length > 0 Then
    Call debugPrintOPML4(strXPathQuery & "[position() = " & n4 + 1 & "]/" & curNode.nodeName)
End If

End Sub

Sub xmldocOpen4()

Dim oFSO As New FileSystemObject ' Microsoft Scripting Runtime Reference
Dim oFS
Dim FilePath As String

FilePath = "rss_awasu.opml"
Set oFS = oFSO.OpenTextFile(CurrentProject.Path & "" & FilePath)
sText4 = oFS.ReadAll
oFS.Close

End Sub

or better:

Sub xmldocOpen4()

Dim FilePath As String

FilePath = "rss.opml"

' function ConvertUTF8File(sUTF8File):
' http://www.vbmonster.com/Uwe/Forum.aspx/vb/24947/How-to-read-UTF-8-chars-using-VBA
' loading and conversion from Utf-8 to UTF
sText8 = ConvertUTF8File(CurrentProject.Path & "" & FilePath)

End Sub

but I don’t understand, why xmldoc4 should be loaded each time.

SierraOscar's user avatar

SierraOscar

17.5k6 gold badges41 silver badges68 bronze badges

answered May 9, 2010 at 2:19

DK.'s user avatar

DK.DK.

911 silver badge2 bronze badges

Update

The procedure presented below gives an example of parsing XML with VBA using the XML DOM objects. Code is based on a beginners guide of the XML DOM.

Public Sub LoadDocument()
    Dim xDoc As MSXML.DOMDocument
    Set xDoc = New MSXML.DOMDocument
    xDoc.validateOnParse = False
    If xDoc.Load("C:My Documentssample.xml") Then
        ' The document loaded successfully.
        ' Now do something intersting.
        DisplayNode xDoc.childNodes, 0
    Else
        ' The document failed to load.
        ' See the previous listing for error information.
    End If
End Sub

Public Sub DisplayNode(ByRef Nodes As MSXML.IXMLDOMNodeList, _
   ByVal Indent As Integer)

   Dim xNode As MSXML.IXMLDOMNode
   Indent = Indent + 2

   For Each xNode In Nodes
      If xNode.nodeType = NODE_TEXT Then
         Debug.Print Space$(Indent) & xNode.parentNode.nodeName & _
            ":" & xNode.nodeValue
      End If

      If xNode.hasChildNodes Then
         DisplayNode xNode.childNodes, Indent
      End If
   Next xNode
End Sub

Nota Bene — This initial answer shows the simplest possible thing I could imagine (at the time I was working on a very specific issue) .
Naturally using the XML facilities built into the VBA XML Dom would be
much better. See the updates above.

Original Response

I know this is a very old post but I wanted to share my simple solution to this complicated question. Primarily I’ve used basic string functions to access the xml data.

This assumes you have some xml data (in the temp variable) that has been returned within a VBA function. Interestingly enough one can also see how I am linking to an xml web service to retrieve the value. The function shown in the image also takes a lookup value because this Excel VBA function can be accessed from within a cell using = FunctionName(value1, value2) to return values via the web service into a spreadsheet.

sample function


openTag = ""
closeTag = "" 

' Locate the position of the enclosing tags startPos = InStr(1, temp, openTag) endPos = InStr(1, temp, closeTag) startTagPos = InStr(startPos, temp, ">") + 1 ' Parse xml for returned value Data = Mid(temp, startTagPos, endPos - startTagPos)

bluish's user avatar

bluish

25.9k27 gold badges120 silver badges179 bronze badges

answered Apr 21, 2011 at 16:30

Tommie C.'s user avatar

Tommie C.Tommie C.

12.8k5 gold badges81 silver badges98 bronze badges

0

Here is a short sub to parse a MicroStation Triforma XML file that contains data for structural steel shapes.

'location of triforma structural files
'c:programdatabentleyworkspacetriformatf_imperialdataus.xml

Sub ReadTriformaImperialData()
Dim txtFileName As String
Dim txtFileLine As String
Dim txtFileNumber As Long

Dim Shape As String
Shape = "w12x40"

txtFileNumber = FreeFile
txtFileName = "c:programdatabentleyworkspacetriformatf_imperialdataus.xml"

Open txtFileName For Input As #txtFileNumber

Do While Not EOF(txtFileNumber)
Line Input #txtFileNumber, txtFileLine
    If InStr(1, UCase(txtFileLine), UCase(Shape)) Then
        P1 = InStr(1, UCase(txtFileLine), "D=")
        D = Val(Mid(txtFileLine, P1 + 3))

        P2 = InStr(1, UCase(txtFileLine), "TW=")
        TW = Val(Mid(txtFileLine, P2 + 4))

        P3 = InStr(1, UCase(txtFileLine), "WIDTH=")
        W = Val(Mid(txtFileLine, P3 + 7))

        P4 = InStr(1, UCase(txtFileLine), "TF=")
        TF = Val(Mid(txtFileLine, P4 + 4))

        Close txtFileNumber
        Exit Do
    End If
Loop
End Sub

From here you can use the values to draw the shape in MicroStation 2d or do it in 3d and extrude it to a solid.

SierraOscar's user avatar

SierraOscar

17.5k6 gold badges41 silver badges68 bronze badges

answered Jan 12, 2015 at 18:30

Bob Wheatley's user avatar

Often it is easier to parse without VBA, when you don’t want to enable macros. This can be done with the replace function. Enter your start and end nodes into cells B1 and C1.

Cell A1: {your XML here}
Cell B1: <X>
Cell C1: </X>
Cell D1: =REPLACE(A1,1,FIND(A2,A1)+LEN(A2)-1,"")
Cell E1: =REPLACE(A4,FIND(A3,A4),LEN(A4)-FIND(A3,A4)+1,"")

And the result line E1 will have your parsed value:

Cell A1: {your XML here}
Cell B1: <X>
Cell C1: </X>
Cell D1: 24.365<X><Y>78.68</Y></PointN>
Cell E1: 24.365

answered Nov 30, 2016 at 22:13

TJ Wilkinson's user avatar

Read XML using Excel VBA

XML is the file format that is widely used to transfer data over internet or between 2 systems with different platforms. The most widely used & familiar xml file in the internet world is the Sitemap.xml. This file has the major links to a website.

Other widely used file formats for data transfer are JSON, CSV. In this article, we are going to learn how to read the xml file using XML DOM (Data Object Model).

Excel VBA XML Parser

Using this tutorial you can build a XML parser using Excel VBA. Lets start with this step by step procedure. Open an Excel Workbook & Open VB Editor by pressing Alt + F11. Then follow these important steps.

  1. Add reference to “Microsoft XML, V6.0” from Excel VB editor.
    • VB Editor -> Menu->Tools -> Reference
    • Scroll down till Microsoft XML, V2.0 or 3.0 or 6.0 appears. The version of XML depends on the OS & Office version installed in your machine.
    • Click Ok.
  2. Now, Copy paste the code to your VBE.
  3. Download a file from Internet or if you have a file already, Modify the xml file path in the code.
  4. Run the code by pressing F5.
'--------------------------------------------------------------------------------
'Code by author@officetricks.com
'Visit https://officetricks.com to get more Free & Fully Functional VBA Codes
'--------------------------------------------------------------------------------
Public Sub Xml_To_Excel()
    Dim myURL As String, sFileNamePath As String, dsh As Worksheet, osh As Worksheet
    Dim WinHttpReq As Object, Node As IXMLDOMNode
    Dim xDoc As MSXML2.DOMDocument
    Dim list As MSXML2.IXMLDOMNodeList
    
    'Create XML DOM Object
    Set xDoc = New MSXML2.DOMDocument
    Set osh = ThisWorkbook.Sheets("Sheet2")
    oRow = 1
    
    'This is only a sample xml file - Change the File path to your Xml file path
    fname = "http://www.xmlfiles.com/examples/simple.xml"
    
    'Load Xml file to Object & Process Each node.
    If xDoc.Load(fname) Then
        Set list = xDoc.SelectNodes("//breakfast-menu/food")
        loopCount = 0
        Application.Wait DateAdd("s", 5, Now)
        DoEvents
        For Each Node In list
            oRow = oRow + 1
            '***Note: node names are Casesensitive***
            osh.Range("A" & oRow) = Node.SelectSingleNode("name").Text
            osh.Range("B" & oRow) = Node.Text
        Next
    Else
        MsgBox "Error Occured"
    End If
    
    MsgBox "Process Completed"
End Sub

This code uses XML DOM model to parse each node from input xml file. Then write it to the Excel file one by one.

  1. Importance of an XML Parser
  2. Build XML Parser Using VBA
  3. Conclusion

Parsing XML in Microsoft Excel VBA

This article will teach us how to parse XML files in VBA.

Importance of an XML Parser

As a Microsoft Excel user, it is common that you might receive some data in the form of an XML file. You will have to retrieve the information from the XML file and use it in your sheets or VBA macros according to your requirement.

A way to do this is to treat it as a text file and parse the information. But this is not an elegant way to parse XML files since the information is stored well-structured using tags, and treating it as a text file negates this concept.

Therefore, we will have to make use of an XML Parser. An XML Parser reads the XML file and retrieves the relevant data so it can be used readily.

Build XML Parser Using VBA

We can parse an XML file using VBA and convert the data into our Excel sheet. The method we will be using uses the XML DOM implementation, short for the XML Document Object Model, and this model allows us to represent the XML file as an object we can then manipulate as required.

To start parsing your XML file through VBA, you must perform a simple sequence of steps. These are explained below.

To parse XML through VBA, you need to have MSXML.4.0 or greater on your system.

  • Add Reference to Microsoft XML

    First, you need to add a reference to Microsoft XML, V6.0 in the VBA Editor. This is how it is done:

    Open the VBA Editor from the Developer tab in Excel.

  • Go to References

  • Scroll down and check Microsoft XML, V6.0, then click on OK.

    Add Microsoft XML V6.0 Reference

    Note that the version of Microsoft XML depends on the operating system and Microsoft Office installed on your computer.

  • Write VBA Code to Load the XML File Into XML DOM

    Suppose we have the following XML file:

    <?xml version="1.0" encoding="ISO8859-1" ?>
    <menu>
    <food>
    <name> Halwa Puri </name>
    <price> $7.50 </price>
    <description> Halwa Puri is from Indian and Pakistani cuisines, having the sweet Halwa and the savory Puri which is a fried flatbread. </description>
    <calories> 900 </calories>
    </food>
    </menu>
    

    We can use the following code to parse this XML file through VBA by making an XML DOM object in the following way:

    Sub XMLParser()
    
    Dim xDoc As New MSXML2.DOMDocument60
    Dim node As IXMLDOMElement
    Set xDoc = New MSXML2.DOMDocument60
    
    With xDoc
    .async = False
    .validateOnParse = True
    
    If xDoc.Load("D:VBAexample.xml") = False Then
    Debug.Print .parseError.reason, .parseError.ErrorCode
    Exit Sub
    End If
    
    Set node = xDoc.SelectSingleNode("//price")
    MsgBox node.Text
    End With
    
    End Sub
    

In the code above, we have first created a variable xDoc of the MSXML2.DOMDocument60 type. Here, we have appended 60 at the end because we are using version 6.0 of Microsoft XML, and without the 60, this code will generate a compile-time error of User-defined type not found.

Next, we have specified that we are working with the xDoc variable using the With statement. The .async property defines permission for asynchronous downloads, and the .validateOnParse property indicates if the parser should validate the XML document.

After that, we use the .Load function to load the specified XML file into the DOM variable. Here, you can change the path and file name to the one on your computer.

The next two lines are for error handling in case the XML file is not loaded properly. To test if the loading has worked, we take one node from the file and specify its name as price.

You should note that the node name is case-sensitive and must be specified according to your XML file. Finally, we display the price using the node.Text property in a message box.

Output:

Load the XML File Into XML DOM

This shows that the loading has worked perfectly fine.

One way to use the XML file data is to store it in an Excel sheet. Let us make a few changes to the code above to store the data in the Excel sheet:

Sub XMLParser()

Dim xDoc As New MSXML2.DOMDocument60
Set xDoc = New MSXML2.DOMDocument60
Dim list As MSXML2.IXMLDOMNodeList
Dim osh As Worksheet
Set osh = ThisWorkbook.Sheets("Sheet1")
oRow = 1

With xDoc
.async = False
.validateOnParse = True

If xDoc.Load("D:VBAexample.xml") = False Then
Debug.Print .parseError.reason, .parseError.ErrorCode
Exit Sub
End If

Set list = xDoc.SelectNodes("//price")
loopCount = 0
For Each node In list
oRow = oRow + 1
osh.Range("A" & oRow) = node.Text
Next
End With

End Sub

Here, we are retrieving all the price nodes and storing them in the sheet. In this example, we have only one price node that will be saved into the sheet as follows:

use the XML file data to store it in an Excel sheet

You can tweak the code according to your XML file and requirements.

Conclusion

This sums up our discussion on the method to parse XML files through VBA. In this article, we have learned how to build an XML parser using XML DOM in VBA.

Reading XML into Excel

One interesting use for Excel is using it as a platform for calling web services.
While the Web Browser is the obvious platform for sending and receiving web based data,
sometimes Excel is a better application to analyse formatted lists or numerical data.
Excel gives you the ability to import and query data via web services.

Excel VBA — Loading XML string defined in program into VBA XML DOM Document

In this example we define an XML string, load the string and use it to populate a DOM document.

Sub XMLTest01()
    'In Tools > References, add reference to "Microsoft XML, vX.X" before running.
	
    'create instance of the DOMDocument object:
    Dim xmlDoc As MSXML2.DOMDocument
    Set xmlDoc = New MSXML2.DOMDocument
    
    Dim strXML As String
    
    'create XML string
    strXML = "<fullName>" & _
                "<firstName>Bob</firstName>" & _
                "<lastName>Smith</lastName>" & _
            "</XXXfullName>"
    
    ' use XML string to create a DOM, on error show error message 
    If Not xmlDoc.LoadXML(strXML) Then
        Err.Raise xmlDoc.parseError.ErrorCode, , xmlDoc.parseError.reason
    End If
	
End Sub	

XML error message: Note that there is an error in the terminating the XML fullname tag

Some VBA vocabulary

MSXML2.DOMDocument The DOMDocument object represents the top node in the tree. It implements all of the base Document Object Model (DOM) document methods and provides additional members that support Extensible Stylesheet Language (XSL) and XML transformations. Only one object can be created: the document. All other objects are accessed or created from the document.

LoadXML Loads an XML document using the supplied string.

Loading XML in Excel VBA — Enhanced error reporting

Sub XMLTest02()
    'In Tools > References, add reference to "Microsoft XML, vX.X" before running.
    
    'create instance of the DOMDocument class:
    Dim xmlDoc As MSXML2.DOMDocument
    Set xmlDoc = New MSXML2.DOMDocument
    
    Dim strErrText As String
    Dim xmlError As MSXML2.IXMLDOMParseError
        
    Dim strXML As String
    
    'create XML string
    strXML = "<fullName>" & _
                "<firstName>Bob</firstName>" & _
                "<lastName>Smith</lastName>" & _
             "</XXXfullName>"
    
    ' use XML string to create a DOM, on error show error message
    If Not xmlDoc.LoadXML(strXML) Then
        
        ' get the ParseError object
        Set xmlError = xmlDoc.parseError
        With xmlError
        strErrText = "Your XML Document failed to load" & _
          "due the following error." & vbCrLf & _
          "Error #: " & .ErrorCode & ": " & xmlError.reason & _
          "Line #: " & .Line & vbCrLf & _
          "Line Position: " & .linepos & vbCrLf & _
          "Position In File: " & .filepos & vbCrLf & _
          "Source Text: " & .srcText & vbCrLf
        End With
        
        ' Display error & exit program
        MsgBox strErrText, vbExclamation
        Set xmlDoc = Nothing
        End
        
    End If
    
End Sub

XML error message: Note that there is an error in the terminating the XML fullname tag

Reading an XML file into Excel

'In Tools > References, add reference to "Microsoft XML, vX.X" before running.
Sub subReadXMLStream()
    
    Dim xmlDoc As MSXML2.DOMDocument
    Dim xEmpDetails As MSXML2.IXMLDOMNode
    Dim xParent As MSXML2.IXMLDOMNode
    Dim xChild As MSXML2.IXMLDOMNode
    Dim Col, Row As Integer

    Set xmlDoc = New MSXML2.DOMDocument
    xmlDoc.async = False
    xmlDoc.validateOnParse = False
    ' use XML string to create a DOM, on error show error message
    If Not xmlDoc.Load("http://itpscan.info/blog/excel/xml/schedule.xml") Then
        Err.Raise xmlDoc.parseError.ErrorCode, , xmlDoc.parseError.reason
    End If
        
    Set xEmpDetails = xmlDoc.DocumentElement
    Set xParent = xEmpDetails.FirstChild
    
    Row = 1
    Col = 1
    
    Dim xmlNodeList As IXMLDOMNodeList
    
    Set xmlNodeList = xmlDoc.SelectNodes("//record")
    
    For Each xParent In xmlNodeList
        For Each xChild In xParent.ChildNodes
            Worksheets("Sheet1").Cells(Row, Col).Value = xChild.Text
            Debug.Print Row & " - "; Col & " -  " & xChild.Text
            Col = Col + 1
        Next xChild
        Row = Row + 1
        Col = 1
    Next xParent
End Sub

Some VBA vocabulary

MSXML2.IXMLDOMNode The IXMLDOMNode object provides methods that represent the core functionality of any node.

async XML DOM property that specifies whether asynchronous download is permitted.

validateOnParse XML DOM property that indicates whether the parser should validate this document.

FirstChild Gets the first child of the node.

output in MS Excel:

Clear cache

This code is useful if you are using Apache Basic Athorization and user changes their userid/password.
Even if the code creates a brand new XMLHttpReq object and sets this header to the new information,
it logs in to the server as the first user, presumably from cached credentials. This code eventively clears the cache
in most browsers and lets user log in with a new username/password combination.

Sub subClearCache()
    
    ' force browser to clear cache
    myURL = "http://172.16.50.250/blackberry/BBTESTB01.pgm"
    Dim oHttp As New MSXML2.XMLHTTP
    oHttp.Open "POST", myURL, False
    oHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    oHttp.setRequestHeader "Cache-Control", "no-cache"
    oHttp.setRequestHeader "PragmaoHttp", "no-cache"
    oHttp.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
    oHttp.setRequestHeader "Authorization", "Basic " & Base64EncodedUsernamePassword
    oHttp.send "PostArg1=PostArg1Value"
    Result = oHttp.responseText
    
End Sub

In my previous articles, we discussed how VBA in Excel can be used for reporting, creating ribbons for your macros, and how to connect an Excel file as a database with SQL support. Working with a database within Excel is a very convenient feature you may use for gathering and storing of data. Nowadays, however, modern object databases and big data platforms prefer formats like JSON (Avro) or XML in general.

Definitions and Declarations

Most modern languages like Python or Ruby have standard XML parsers in-built. As VBA has been here for decades, neither much maintained, nor developed, the support is not that straight-forward. There is, however, a good tool set you may use for processing XMLs in your macros. Firstly, let’s define the objects we will work with:

Public Function ParseXML(p_path As String) As Object
    Dim objDom As Object                                    '// DOMDocument
    Dim strData As String
    Dim objStream As ADODB.Stream

    Set objDom = CreateObject("Msxml2.DOMDocument.3.0")     '// Using MSXML 3.0;                         
        'you may use DOMDocument.4.0 for MSXML 4.0
    Set objStream = New ADODB.Stream 'CreateObject("ADODB.Stream")
    
    objStream.Charset = "UTF-8"
    objStream.Open
    objStream.LoadFromFile (p_path)
    
    strData = objStream.ReadText()
    
    objStream.Close
    Set objStream = Nothing
    
    objDom.LoadXML strData
    
    Set ParseXML = objDom
End Function

The code is quite self-explanatory. I pasted the whole function, so feel free to use it directly as-is, just pass the source XML file path as an argument and don’t forget about error handling.

Accessing XML Data

Now let’s have a look at the functions we may use for data extraction. The basic looping through the XML nodes may be implemented as follows:

For Each listNode In rootNode.ChildNodes
    If listNode.HasChildNodes Then
        ' do something
    End If
Next listNode

Accessing the data of the actual node:

<SingleNode Id="N1" Text="NodeValue" Required="true" Look="Standard">
    TheText
</SingleNode>

Would follow the below syntax:

str = listNode.BaseName            ' Extracts "SingleNode" value
str = listNode.Attributes(0).Text  ' Extracts "N1" value
str = listNode.Text                ' Extracts "TheText" value

Other standard traversing methods you might need are also supported – for a more comprehensive overview, you may want to check this article. Node referencing:

XML representation:

<?xml version="1.0" encoding="utf-8"?>
<RootElement>
    <Node ID="1">
        <Node ID="1.1" />
    </Node>
    <Node ID="2">
        <Node ID="2.1" />
        <Node ID="2.2" />
        <Node ID="2.3" />
        <Node ID="2.4" />
    </Node>
    <Node ID="3" />
</RootElement>

In case you need to access a specific node directly and you don’t need control of the actual traversing, you may also use the XPath methods.

That is it for now, have fun working with your XMLs. Is there anything else you would like to know about VBA and macros in MS Office? Just drop me a message and I might discuss it in the next article. Thanks for reading!

Введение в XML DOM

Передача набора записей из VB-приложения в Excel

    Импорт данных

    Ввод данных

    Вопросы перекодировок
данных

Вывод данных о свойствах Word-документа

Создание архива входящей почты

Одна из «горячих» ИТ-тем нынешнего года — проблема интеграции разнородных
информационных ресурсов, решение которой требует создания простого и надежного
механизма обмена данными между различными приложениями. И сегодня, кажется,
все уже знают: XML — тот золотой ключик, который должен открыть дверь в
новый мир, где порядок наконец заменит собой существующий ныне информационный
хаос великого множества форматов данных.

Напомним, что XML и
HTML базируется
на одинаковых синтаксических принципах —
информация записывается в виде простого
текста, в котором имеются управляющие
команды (тэги) и собственно данные. XML
отличается от HTML
тем, что позволяет
передавать не только данные, но также и
информацию об их структуре, то есть HTML
ориентирован на
описание неструктурированных данных, а XML — структурированных.
С точки зрения использования информации
неструктурированные данные предназначены
в первую очередь для визуального
восприятия человеком, струкутрированные —
для автоматической обработки (в том числе
вычислений). Отметим, что оба этих языка
представляют собой упрощенный вариант
давно известного среди компьютерных
лингвистов языка SGML (Standard Generation
Markup Language).

Подчеркнем, что
в принципе
сама идея
языка
XML — текстового
описания
структуры
и содержания
некоторых
данных — совсем
не нова.
Новизна
заключается
лишь в
том, что
лидеры компьютерной
индустрии
вроде бы
осознали
необходимость
перехода
от внутренних,
закрытых,
форматов
к общим,
открытым.
Но, честно
говоря,
о том,
насколько
серьезны
эти намерения
(а не
маркетинговые
акции, предназначенные
для показа
своей готовности
к открытости),
можно будет
судить лишь
спустя некоторое
время.
XML — это
мировой
отраслевой
стандарт,
создание
и развитие
которого
ведется
под эгидой
WWW Consortium, общественной
организации,
представляющей
интересы
входящих
в нее
участников
рынка.

Что касается
прикладных
программистов,
то они
уже очень
давно оценили
преимущества
простых
текстовых
форматов
данных по
сравнению
с двоичными
при информационном
взаимодействии
компонентов
вычислительных
систем.
Могу сослаться
на пример
из собственной
программистской
практики
десятилетней
давности.
При разработке
информационно-аналитических
систем для
обработки
геологических
данных мы
полностью
перешли
на текстовые
форматы
данных и
описаний
их структуры,
резко сократив
время на
отладку
программного
комплекса
и его
конфигурирование
под задачи
пользователей.
Сначала
мы рассматривали
такое решение
как временное
и хотели
для повышения
производительности
перейти
на двоичные
форматы.
Но жизнь
показала,
что это
пустая трата
времени,
так как
производительность
компьютеров
росла быстрее,
чем объем
базы данных.


Здесь следует
сделать
одно важное
замечание.
Текстовое
представление
данных имеет
свои недостатки.
Один из
них — сложности
с использованием
символов,
задействованных
в качестве
специальных
(например,
«<» и
«>»). Вторая
проблема
заключается
в неоднозначности
преобразования
данных из
внутреннего
двоичного
формата
в текст,
и наоборот.
В последнем
случае особое
внимание
нужно уделять
национальной
специфике
форматов,
особенно
при работе
с разными
региональными
установками
и кодовыми
таблицами.

Понятно, что
появление
общего стандарта
описания
данных избавляет
разработчиков
от необходимости
придумывать
собственные
форматы.
Однако за
любую универсальность
приходится
расплачиваться
определенной
избыточностью,
хотя в
данном случае
она будет
не так
велика и
не будет
сколь-нибудь
заметна
на современных
компьютерах.
Например,
мне бы
пришлось
заменить
свои старые
описания
параметров:

 LastName = Колесов

на:

 <LastName>Колесов</LastName>

Прежде чем перейти к конкретным техническим вопросам, стоит сделать еще одно
важное замечание. Сам по себе XML не решает проблемы преобразования XML-документов,
что необходимо для передачи данных между приложениями. Проще говоря, XML лишь
связывает, например, некоторый набор чисел с понятием (тэгом) «цена», но что
именно означает данный термин, язык уже не может расшифровать. Таким образом,
для правильной интерпретации содержимого XML-документов необходимо знать так
называемую XML-схему, которая бы описывала смысл полей данных.

Введение в XML DOM

Visual Basic 6.0 и
приложения MS Office 2000 не
включают в себя поддержку XML на
уровне пользователя и разработчика, хотя
при этом многие приложения Office используют
передачу данных с помощью XML для
выполнения внутренних операций. Вместе с
тем уже сегодня, не дожидаясь новых версий
этих систем (где что-то, связанное с XML,
должно вскоре
появиться), программисты могут применять XML-формат
для обмена информацией с помощью написания
собственных достаточно простых
программных конструкций. Видятся два пути
реализации этой задачи:

  1. Использование специального объекта XML, называемого XMLDOM, или DOMDocument
    (DOM, Document Object Model). Работа с этим объектом выполняется с помощью
    библиотеки Microsoft XML 2.0 (MSXML.DLL), на которую нужно сделать ссылку
    в окне Reference. (Обратите внимание: на моем компьютере в списке ссылок эта
    библиотека в начальный момент имеет индекс 1.0, а уже после ее подключения
    меняет его на 2.0.)

    С точки зрения программиста в применении DOMDocument можно выделить три
    момента:

    • формирование структуры и содержания документа, а также выборка из него
      необходимой информации;
    • преобразование объекта из внутреннего формата во внешний текстовый
      XML-файл (в том числе вставка объекта в уже существующий файл), и наоборот;
    • возможность передачи объекта внутри приложения, а также обеспечение
      доступа к нему из других приложений с помощью ActiveX.
  2. На практике наиболее распространенной задачей является экспорт-импорт с
    помощью XML-файла, что можно делать с помощью обычных средств VB/VBA. Вывод
    данных в формате XML является вообще достаточно тривиальной задаче. С вводом
    дело обстоит посложнее, так как в этом случае нужно «вручную» писать код для
    анализа синтаксиса и для разборки элементов документа. Как бы то ни было,
    в любом случае программист должен иметь в виду «ручной» метод экспорта-импорта,
    который иногда может быть очень полезен.
В начало

В начало

Передача набора записей из VB-приложения в Excel

В наших «Советах для тех, кто программирует на VB» мы приводили два примера
импорта данных из таблицы (набора записей, Recordset) в виде просто текстового
файла (совет 297) и HTM-файла (совет 329). Попробуем выполнить аналогичную задачу
с помощью XML-файла, который потом прочитаем в Excel.

В начало

В начало

Импорт данных

Для тестирования мы сделаем базу данных с
таблицей такого содержания:

FirstName

LastName

BirthDate

Height

Sergey

Sokolov

03.11.52

1,82

Андрей

Petrov

17.08.58

1,77

Света

Суслова

23.09.67

1,65

Далее напишем код, который обращается для импорта данных к процедуре ExportXML
(листинг 1):

Dim strConnectString$, strSQL$, strHeading$
      Dim cnn As ADODB.Connection
      Dim rs As Recordset 
strConnectString = "Provider=Microsoft.Jet.OLEDB.3.51;" & _       "Persist Security Info=False;" & _       "Data Source=C:vb-dbxmltest.mdb" strSQL = "Select FirstName +' ' + LastName as Name, " & _       "BirthDate, Height as Рост" & _       " from Employees Order by LastName, FirstName" strHeading = "Список сотрудников"
Set cnn = New ADODB.Connection    Set rs = New ADODB.Recordset    cnn.Open strConnectString$ ' устанавливаем связь    Set rs = cnn.Execute(strSQL) ' создаем Recordset
   Call ExportXML(rs, strHeading$, "d:file1.xml")

В результате его выполнения получим XML-файла, содержимое которого лучше всего
посмотреть в Internet Explorer (рис.1). Для понимания
выполненных нами действий нужно отметить следующие моменты:

  • в IE 5.0 мы видим почти точное содержимое XML-файла (в отличие от HTML,
    когда браузер выдает документ в отформатированном виде). В содержительном
    плане мы увидели бы то же самое с помощью Notepad, но с некоторыми отличиями
    по форме. В частности, физически файл, сформированный при сохранении документа
    с помощью объекта DOMDocument, представляет одну тестовую строку с
    переводом строки (vbCrLf) в конце. Internet Explorer представил ее в виде
    структурированного иерархического дерева, которое можно просматривать, открывая
    и закрывая его узлы;
  • мы специально использовали в исходных данных русские тексты, чтобы показать,
    что их можно использовать для передачи как названий полей (тэгов), так и их
    содержимого. По умолчанию в XML-файл русский текст записывается в двухбайтовой
    кодировке UTF-8 (это можно увидеть в редакторе Notepad), но при использовании
    параметра encoding можно применять и другие кодировки;
  • имена элементов (тэгов) не могут включать пробелы. Поэтому мы с помощью
    оператора Replace автоматически меняем возможные пробелы на символ подчеркивания.

Создание нового объекта DOMDocument
начинается со
строки кода:

Dim xmlDoc As DOMDocument
Set xmlDoc = New DOMDocument
StartString$ = "<?xml version='1.0'?>" ' начальная строка 
                                                             ' (может отсутствовать)
MainNode$ = "<Главный_узел_объекта/>"   главный узел объекта
xmlDoc.loadXML StartString$ + MainNode$

Для выбора кодировки передаваемых данных
нужно сформировать начальную строку
следующего вида:

StartString$ = "<?xml version='1.0' encoding='Windows-1251'?>"

Однако мне этого не удалось сделать — выдавалось сообщение о невозможности
создания объекта.

В начало

В начало

Ввод данных

Для ввода сформированного XML-файла в Excel используем функцию ImportXML (листинг
2).

Эта функция создает объект DOMDocument, который
можно затем дополнительно обрабатывать, и
записывает введенные значения в рабочую
таблицу. Ввод данных можно сделать с
помощью такой макрокоманды:

 Sub MyMacro()
    Set mXML = ImportXML("D:file1.xml")
End Sub

В результате ее выполнения мы получим заполненную таблицу рабочей книги (рис.
2).

Теперь внимательно рассмотрим, как производится ввод данных из созданного нами
XML-файла. Обращение к функции ImportXML (Excel) в общем случае выглядит следующим
образом:

    Set mXML = ImportXML(xmlFile$, ObjectPath$, PropertyPath$)

Если мы используем установку ObjectPath
= «*» (по
умолчанию), то работа ведется во всеми
объектами документа. В нашем случае это
будут узлы с тэгами <OneRowI> (они
могут иметь произвольные имена, в том числе
одинаковые, например <OneRow>), а
включенные в них тэги — свойствами. При
формировании таблицы в Excel для
определения имен колонок мы анализировали
содержимое только первого узла, считая все
узлы однородными.

Однако если мы укажем ObjectPath = «<//OneRow2>», то выборка
будет сделана только для данного узла. Точно так же можно управлять выборкой
отдельных полей, например указав PropertyPath = «BirthDate».

В начало

В начало

Вопросы перекодировок данных

Анализируя выполненные нами операции по передаче данных, в первую очередь
следует обратить внимание на то, что все данные (содержимое полей набора записей)
передаются в виде текста. Преобразование информации в нашем случае выполнялось
средствами VB, и поэтому был автоматически выбран формат в соответствии с текущими
региональными установками. Принимающее приложение (Excel) также получило обычные
текстовые данные, которые в принципе могут быть интерпретированы самым произвольным
образом. Имейте в виду, что ячейки таблицы (рис. 2) заполнены
обычным текстом в неопределенном формате (внешний признак этого — выравнивание
по левому краю).

Подобная ситуация чревата ошибками при
передаче XML-данных
между компьютерами, имеющими разные
региональные установки (для Америки
значение «23.09.53» является недопустимой
датой, а «1,23» — недопустимым числом). Для
решения этой проблемы есть несколько путей.
Во-первых, можно применять
пользовательские атрибуты, которые будет
понимать как передатчик, так и приемник
информации. Во-вторых, можно присвоить
каждому свойству узла «жесткий» тип данных,
и тогда будет использоваться
соответствующий фиксированный формат.

Для реализации первого способа немного
модифицируем код функции RecordsetToXMLDOM:

 For Each fldField In rs.Fields   ' запись полей записи
   ' создание нового элемента
   Set xmlField = xmlFields.appendChild( _
      xmlDoc.createElement(Replace(fldField.Name, " ", "_")))
   ' установка атрибута "MyType"
   Set attr = xmlDoc.createAttribute("MyType")
   attr.Value = fldField.Type
   xmlField.Attributes.setNamedItem attr
   
   xmlField.Text = fldField.Value   ' запись содержимого
Next

В результате этого в сформированном коде
в тэги с наименованием полей добавятся
атрибуты с

кодами типов данных (рис. 3). Соответственно
при вводе данных их значения можно прочитать и сделать соответствующую установку
форматов ячеек:

DateType = propertyNode.Attributes(0).nodeValue

Для второго варианта нужно использовать
фиксированный, закрепленный за типом
данных формат. Например, для переменных
типа «дата» установку такого атрибута
можно выполнить так:

 Set attr = xmlDoc.createAttribute("dt:dt")
attr.Value = "date"
xmlField.Attributes.setNamedItem attr

или воспользоваться свойством dataType:

xmlField.dataType = "date"

В этом случае записываемые данные должны
иметь обязательный формат даты «ГГГГ-ММ-ДД»:

xmlField.Text = "2000-12-02"

Нужно также отметить, что тип поля необязательно задавать в каждом тэге. Можно,
например, один раз сделать такое описание всех полей при формировании узла или
всего документа (в том числе со ссылкой на XML-схему).

В начало

В начало

Вывод данных о свойствах Word-документа

Теперь попробуем решить такую задачу: будем формировать протокол работы с
документами Word 2000, записывая информацию о встроенных свойствах при завершении
работы с документом. Для начала напишем функцию DocPropertiesToXML, формирующую
DOMDocument-объект для одного документа Word (листинг 3).

Поместим эту функцию в модуль в составе
глобального шаблона Normal.dot (нужно
также для шаблона указать ссылку на MSXML.DLL).
Далее создадим
макрокоманду, которая будет формировать XML-файл
для одного документа:

Public Sub OneDocPropertyToXML()
   Dim xmlDoc As DOMDocument    Set xmlDoc = DocPropertiesToXML(ThisDocument)     'можно создавать файл с оригинальным именем    xmlDoc.Save "d:Myfile.xml" End Sub

В результате мы получим файл со свойствами одного документа (фрагмент файла
изображен на рис. 4):

Содержимое полученного файла можно
прочитать созданной ранее процедурой ImportXML
в Excel, но
для этого обращение к ней должно выглядеть
следующим образом (главный узел следует
указать в качестве объекта):

Set mXML = ImportXML("D:myfile.xml", "//DocProperties")

Напишем процедуру DocPropertyToLogXML, которая будет создавать файл протокола
(листинг 4).

Обратите внимание на операции включения
созданного для конкретного документа XML-объекта
в объекта Log-файла.
Теперь создадим макрокоманду, которая
будет добавлять информацию об активном
документе в протокол:

Call DocPropertyToLogXML(ThisDocument)

В результате вы будет автоматически формировать XML-файл, структура которого
приведена на рис. 5). Его также можно прочитать
в Excel:

Set mXML = ImportXML("D:logfile.xml")

Примечание. Обращение на запись информации в Log-файл можно поместить
в процедуру ThisDocument_Close каждого документа. Механизм программного формирования
такого кода в каждом открываемом файле описан в статье Владимира Биллига «Документы
Office 2000 и их проекты» (http://www.microsoft.ru/offext/officedev/).

В начало

В начало

Создание архива входящей почты

Приведем еще один пример использования XML-файла — на этот раз для хранения архива
поступающей электронной почты. Для этого
нужно сначала сформировать две событийные
процедуры:

 Dim mailBagFileName As String
Dim AttachmentsDirectory As String
Private Sub Application_Startup()     ' Инициализация при запуске прилежения       ' файл с архивом входящей почты       mailBagFileName = "d:/xmlPro/mailBag.xml"       ' каталог для хранения присоединенных файлов       AttachmentsDirectory = "d:/xmlPro/" End Sub
Private Sub Application_NewMail()     ' При поступлении нового письма производится запись его в архив       Dim mailItems As Items       Dim mailmsg As MailItem             ' Папка с входящими письмами       Set mailItems = Application.Session.GetDefaultFolder( _          olFolderInbox).Items       Set mailmsg = mailItems.GetLast ' выбираем последнее       ' Запись поступившего письма в XML-объект       Set xmlMail = MessageToXML(mailmsg, AttachmentsDirectory)     ' запись в архив       Call AddMessageToArchive(xmlMail, mailBagFileName) End Sub

Ключевым процедурами в этой задаче являются процедуры MessageToXML и AddMessageToArchive
(листинг 5).

Общая логика формирования архива очень похожа на то, что мы делали, создавая
протокол работы с Word-файлами: сначала преобразуем содержимое письма в DOMDocunemt,
а потом подключим его к единому файлу. Новшеством здесь является то, что документ
письма имеет более сложную структуру (появились вложенные узлы для описания
подключенных файлов), и для хранения тела письма мы используем секцию CDATA
(содержимое письма может иметь символы, нарушающие синтаксис XML). Результат
преобразования в XML показан на рис. 6.

Чтобы закончить с этой задачей, остается только написать ASP-cтраницу (листинг
6) которая преобразует содержимое XML-архива писем в HTML-формат (рис.
7).

КомпьютерПресс 12’2000

VBA XML

Excel VBA XML

The full form of XML is eXtensible Markup Language which is much like an HTML file, is designed to store and transport the data from different programs. XML file stores the data which includes the splits and separators. We can create a VBA code by which we can import the data from the XML file into Excel. In order to import the data from the XML file to any other format, we need to set some rules which tells what kind of data and fields can be used in the XML file. To create a macro in VBA for the XML file, we do not mandatory need XML Notepad in our system. But if we have it will be easy for us to read the XML file for the data we need.

Although in Excel, we have a provision of importing the data of XML file but using VBA, we can read, import the XML file in Excel.

Types of Node in VBA XML

In XML, we have a variety of Nodes that constructively helps in reading and parsing the XML file into other sources such as Word or Excel. Each DocumentElement refers to some of the nodes lists below.

  • Parent Node
  • First Child
  • Last Child
  • Child Nodes
  • Next Sibling
  • Previous Sibling

All the above-mentioned nodes confirm the type as [XDoc.DocumentElement], where only Child nodes are the array type of [XDoc.DocumentElement].

In this example, we will see a very simple VBA Code to access the XML file saved in the individual system’s any location and load them into VBA. Usually, to import XML files in Excel using VBA, we have  MSXML2.DOMDocument object to allow us to transverse the data through XML structure. But this may not be used in this example.

For this, we must have an XML file in which we can create a data structure in the form of Schema. Below is the screenshot of Company schema where under that we have Employee branch with the employee details like First Name, Last Name, Contact Number, Email ID.

VBA XML Code

VBA XML Tree

Steps to Import & Add XML in Excel VBA

Below are the examples of XML in Excel by using the VBA Code.

You can download this VBA XML Excel Template here – VBA XML Excel Template

Example #1

Step 1: First go to Insert menu tab in VBA and open a Module where we will be writing the code transverse data through XML as shown below.

Insert Module

Step 2: Write the subprocedure in the name of VBA XML for the definition of the code.

Code:

Sub VBA_XML()

End Sub

VBA XML Example 1-2

Step 3: As we already discussed, for the XML file we will require Object. So, Now define a variable using DIM as String which will be used for storing the File name.

Code:

Sub VBA_XML()

Dim XMLFile As String

End Sub

VBA XML Example 1-3

Step 4: Now we will use an application Display Alerts which is used for showing the alert message if the chosen path is incorrect.

Code:

Sub VBA_XML()

Dim XMLFile As String
Application.DisplayAlerts = False

End Sub

VBA XML Example 1-4

Step 5: Now we will put the link or location where we have kept XML file and assign it to the defined variable.

Code:

Sub VBA_XML()

Dim XMLFile As String
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"

End Sub

VBA XML Example 1-5

Note: Keep the XML file in the location which is easy to access.

Step 6: As we discussed, we will get the first Object with MSXML2.DOMDoucment.

Code:

Sub VBA_XML()

Dim CusDoc As Object
Dim Base As Object
Set CusDoc = CreateObject("MSXML2.DOMDoucment")

End Sub

VBA XML Example 1-6

Step 7: To load the data of XML file in Excel, we need to open that XML file, using the name and location which we have stored in XML File variable and select the load option as Import to List as shown below.

Code:

Sub VBA_XML()

Dim XMLFile As String
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Workbooks.OpenXML Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList

End Sub

VBA XML Example 1-7

Step 8: At last, again use the Application option to display the alert as TRUE if there is any.

Code:

Sub VBA_XML()

Dim XMLFile As String
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Workbooks.OpenXML Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList
Application.DisplayAlerts = True

End Sub

VBA XML Example 1-8

Step 9: Now we will compile the written code by pressing F8 functional key and run it, if there is no error found during compilation.

We will see, the data stored in the XML file is not imported in a new workbook as shown below. We can fetch any length of data of XML file into Excel using this simple VBA Code.

VBA XML Example 1-8

Example #2

There is another way to import the data of an XML file using the VBA Code which is simple too. For this, we can have another module of we can make the changes in the same module as well.

Step 1: For this again we would require a module and there write the subprocedure in the name of VBA XML.

Code:

Sub VBA_XML2()

End Sub

VBA XML Example 2-1

Step 2: Define a variable as String where we will be storing the file location and another variable for Workbook as shown below.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook

End Sub

VBA XML Example 2-2

Step 3: Now similar to the previous example we will now use 2 Applications, one of Screen updating and other for Display Alerts as FALSE.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False

End Sub

VBA XML Example 2-3

Step 4: Now in the defined variable XMLFile, we will assign the path of the XML file.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"

End Sub

Defined Variable Example 2-4

Step 5: Similar to example-1, we will now update set the code for Opening XML file with the path defined in XMLFile variable and load the data Import to list.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Set WBook = Workbooks.OpenXML(Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList)

End Sub

VBA XML Example 2-5

Step 6: Now again to put the Display alert application as TRUE.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Set WBook = Workbooks.OpenXML(Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList)
Application.DisplayAlerts = True

End Sub

Display Alert Application Example 2-6

Step 7: Once the data is imported we will copy that into another workbook from the selected cell A1:D1 as per the number of headers available in the XML file.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Set WBook = Workbooks.OpenXML(Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList)
Application.DisplayAlerts = True
WBook.Sheets(1).UsedRange.Copy ThisWorkbook.Sheets(1).Range("A1:D1")

End Sub

Workbook Example 2-7

Step 8: At last close the code using Screen updating application as TRUE.

Code:

Sub VBA_XML2()

Dim XMLFile As String
Dim WBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
XMLFile = "C:AshwaniCompany.xml"
Set WBook = Workbooks.OpenXML(Filename:=XMLFile, LoadOption:=xlXmlLoadImportToList)
Application.DisplayAlerts = True
WBook.Sheets(1).UsedRange.Copy ThisWorkbook.Sheets(1).Range("A1:D1")
Application.ScreenUpdating = True

End Sub

Screen updating application Example 2-8

Step 9: Now if we run this code, we will see the data from the XML file will get imported into a new Excel workbook as shown below.

VBA XML Example 2-9

Pros of VBA XML

  • Even if you do not know how to create an XML file and work on it, using such VBA codes, we can extract the data into VBA Code or in Excel.
  • We can parse a portion of XML Data or complete data into the VBA window by using node references.

Things to Remember

  • Every node reference has its own value and meaning. Using the right note type is very important for every condition.
  • XML to VBA is not limited to the code which we have seen in the above examples.
  • We can extract any type of data using the code which we have seen in above-discussed examples. But keep the proper location and path which is easy to access.
  • We can also extract the XML file data without opening it from the developer tab’s Source option. This will help us to get the data as it is into the Excel workbook.
  • Save the written code Excel file in Macro enabled excel format, to avoid losing the code.

Recommended Articles

This is a guide to the VBA XML. Here we discuss Steps to Import & Add XML in Excel VBA and its different types of node along with practical examples and downloadable excel template. You can also go through our other suggested articles –

  1. VBA LBound
  2. VBA Get Cell Value
  3. VBA IsError
  4. VBA Solver

0 / 0 / 0

Регистрация: 27.02.2012

Сообщений: 21

1

15.01.2014, 07:13. Показов 25283. Ответов 8


Студворк — интернет-сервис помощи студентам

Добрый день. Есть такая задача:

  1. Есть xml файл в котором есть перечень сотрудников. Нужно циклом из этого файла фамилию каждого сотрудника выгрузить в отдельную ячейку в екселе. Как сделать это макросом
  2. Как сделать цикл, чтобы он сканировал xml файл до самой последней строки, так как не известно сколько сотрудников будет в нем указано.

Пример файла во вложении



0



Surrogate

Ушел с CyberForum совсем!

873 / 182 / 25

Регистрация: 04.05.2011

Сообщений: 1,020

Записей в блоге: 110

15.01.2014, 11:13

2

Цитата
Сообщение от drzod
Посмотреть сообщение

Есть xml файл в котором есть перечень сотрудников. Нужно циклом из этого файла фамилию каждого сотрудника выгрузить в отдельную ячейку в екселе. Как сделать это макросом

файл xml отрывается ровно также как книги экселя

Visual Basic
1
2
dim wb as workbook
Set wb = Workbooks.Open("c:9070481out9070481out.xml")

В приложенном файле фамилии хранятся в 10-ом столбце, их значения в целевой файл можно считывать так

Visual Basic
1
wb.Sheets(1).Cells(3, 10).Value

Цитата
Сообщение от drzod
Посмотреть сообщение

Как сделать цикл, чтобы он сканировал xml файл до самой последней строки, так как не известно сколько сотрудников будет в нем указано.

тело таблицы начинается с третьей строки, для определения общего количества строк можно использовать цикл

Visual Basic
1
For x = 3 To wb.Sheets(1).UsedRange.Rows.Count

Добавлено через 2 минуты
drzod, а строчку которая будет вытягивать значения из xml в целевую книгу экселя уже за тобой



1



0 / 0 / 0

Регистрация: 27.02.2012

Сообщений: 21

15.01.2014, 11:57

 [ТС]

3

А представьте около 10000 cm файлов. Надо каждый так загружать? ))) хах, решение нашел. Все спасибо за помощь



0



Ушел с CyberForum совсем!

873 / 182 / 25

Регистрация: 04.05.2011

Сообщений: 1,020

Записей в блоге: 110

15.01.2014, 12:03

4

Цитата
Сообщение от drzod
Посмотреть сообщение

А представьте около 10000 cm файлов. Надо каждый так загружать? )))

10000 cm ? это как

Цитата
Сообщение от drzod
Посмотреть сообщение

хах, решение нашел

в чем секрет, если не секрет ?



0



0 / 0 / 0

Регистрация: 27.02.2012

Сообщений: 21

15.01.2014, 12:16

 [ТС]

5

В вашем решении я как понимаю каждую xmlку макрос открывает и это визуально видно. Думаю это может плохо сказаться на производительности.

Вот так подсказали решение. Я потом пот себя переделал. Сделал цикл, чтобы выдергивать имя файла из ячейки, он «открывался» там искались определенные параметры. В случае их обнаружения выполнялось условие

А 10000 строк — ну хз, такой объем данных ))

Добавлено через 45 секунд
тут

Добавлено через 1 минуту
Короче домой приду, кину ссылку. С телефона не удобно ))



0



Ушел с CyberForum совсем!

873 / 182 / 25

Регистрация: 04.05.2011

Сообщений: 1,020

Записей в блоге: 110

15.01.2014, 13:15

6

Цитата
Сообщение от drzod
Посмотреть сообщение

В вашем решении я как понимаю каждую xmlку макрос открывает и это визуально видно. Думаю это может плохо сказаться на производительности.

в моем решении xml открывается один раз и считывает все строки будь их хоть 100500. Или таких xml со списками фамилий не одна ?



0



0 / 0 / 0

Регистрация: 27.02.2012

Сообщений: 21

15.01.2014, 13:28

 [ТС]

7

Их Оооочень много

Добавлено через 1 минуту
В любом случае спасибо вам за помощь. Вы единственный откликнулись



0



Surrogate

Ушел с CyberForum совсем!

873 / 182 / 25

Регистрация: 04.05.2011

Сообщений: 1,020

Записей в блоге: 110

15.01.2014, 15:00

8

Цитата
Сообщение от drzod
Посмотреть сообщение

Их Оооочень много

вчера в этой ветке помогали человеку исправить 150 книг эксель

Добавлено через 24 минуты
если все xml в одной папке то код будет такой

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sub drzod()
Dim TheFolder, TheFiles, AFile
Set FSO = CreateObject("Scripting.FileSystemObject")
Set TheFolder = FSO.GetFolder("c:9070481out") ' папка где лежат все xml
Set TheFiles = TheFolder.Files
For Each AFile In TheFiles
ReadXML (AFile)
Next
End Sub
Sub ReadXML(af As String)
Dim xml_doc As New DOMDocument
Dim nde_test As IXMLDOMElement
xml_doc.Load af
For Each nde_test In xml_doc.SelectNodes("//Сотрудник")
  Debug.Print nde_test.SelectSingleNode("Фамилия").Text
Next
End Sub

Добавлено через 34 минуты

Цитата
Сообщение от drzod
Посмотреть сообщение

В любом случае спасибо вам за помощь. Вы единственный откликнулись

Не единственный, ведь код с DOMDocument тебе на другом форуме присоветовали



0



72 / 0 / 0

Регистрация: 19.06.2014

Сообщений: 68

16.03.2016, 11:32

9

Добрый день.
А как быть, если файл такого вида, меняю и ничего не получается(



0



Понравилась статья? Поделить с друзьями:
  • Читать в word pdf онлайн
  • Чтение word файлов с телефона
  • Читать word на самсунг
  • Чтение word файлов онлайн
  • Читать word на андроид на русском