Dom xml vba excel

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"

Введение в 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

It is pretty easy to exchange data between Excel & VBA and XML file. XML files are one of the most common files other than Txt and CSV. It is easier to read non-hierarchical data files (XML or JSON). You can read the rows and columns differently in the code line. It is not that easy to check data with XML (and JSON.) There are parent-child relations between the records in the templates and the number of underlying nodes can be changed corresponding to the table data that contain a stable number on columns. This has been separated with a certain delimiter.

Fortunately, we can easily exchange data between Excel & VBA and XML file by using the MSXML2.DOMDocument object in VBA.
But, as always, let’s start with a short introduction concerning how to create a while before we deep into the examples of a structure in XML.

Microsoft Excel, makes it easy to import Extensible Markup Language (XML) data created on out databases and applications, pair XML objects coming from XML schema with the workbook cells and export XML data to interact with out databases and applications. You can think of it as these XML features turns Office Excel in to a XML data file creater that works with a familiar user interface.

Now let’s take a look at this VBA & XML.

Upload XML File to VBA

The MSXML2.DomDocument object enables you to access XML structure easily and provides movement between any required node and/or quality with the XML structure. Let’s take a look at the example below.

Sub PEAKUP()
 Dim Xml As Object, root As Object
 Set Xml = CreateObject("MSXML2.DOMDocument")
 Xml.async = False: Xml.validateOnParse = False
 Xml.Load (ThisWorkbook.Path & "etf.xml")
 Set root = Xml.DocumentElement End Sub

XML DOM Nodes in VBA

 XML file will provide you with the root of all the DOM(XDoc.DocumentElement Model).

Each DocumentElement (XML DOM node) facilitated the node references below:

parentNode Parent node, the top node in the DOM hierarchy
firstChild First child node, the first child node in the DOM hierarchy
lastChild Last child node, the last child node in the DOM hierarchy
childNodes All child nodes of the node, all nodes in the DOM hierarchy
nextSibling The same-level node in the same master node in the DOM hierarchy, i.e. the next sibling node.
previousSibling The same-level node in the same master node in the DOM hierarchy, i.e. the previous sibling node.

All the references below help you to access the data in XML DOM.

childNodes

Let’s take the first node as an example and have the text content as MsgBox. We usually use ChildNodes while exploring nodes in XML DOM.

Sub PEAKUP()
    Dim XDoc As Object
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "etf.xml")
    Set lists = XDoc.DocumentElement
    Set ilkdugum = lists.FirstChild
    MsgBox ilkdugum.Xml
    MsgBox ilkdugum.Text
    Set XDoc = Nothing
End Sub

You can download thisVBA ile XML file and test the codes below.

Now that we’ve got all the basic information, we can write the all content of XML to Excel with these codes.

Sub PEAKUP()
    Dim XDoc As Object
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    XDoc.async = False: XDoc.validateOnParse = False
    XDoc.Load (ThisWorkbook.Path & "etf.xml")
    Set lists = XDoc.DocumentElement
    For Each satirNode In lists.ChildNodes
        For Each alandNode In rowNode.ChildNodes
            a = a + 1
            Cells(a, 1) = "[" & alanNode.BaseName & "] = [" & alanNode.Text & "]"
        Next alanNode 
    Next satirNode 
    Set XDoc = Nothing
End Sub

You’ll see that you can do this action with the examples below as well.

XML Attributes in VBA

You can get the attribute values states as current attribute in the XML Nodes. Let’s assume that you have an XML structure like this:

<?xml version="1.0" encoding="utf-8"?>
<AnaDugum>
    <Liste>
        <Adi attribute="PEAKUP">ORG</Adi>

You can get the attributes easily with XPath as shown below.

Set adialani = XDoc.SelectNodes("//AnaDugum/Liste[0]/Adi")
MsgBox adialani(0).Attributes(0).Text

Create an XML File

ub XML_Belge_Olusturma()
    Dim XDoc As Object, root As Object, elem As Object, rel As Object
    Set XDoc = CreateObject("MSXML2.DOMDocument")
    Set root = XDoc.createElement("Root")
        XDoc.appendChild root
    Set elem = XDoc.createElement("Child")
        root.appendChild elem
    Set rel = XDoc.createAttribute("Oznitelik")
        rel.NodeValue = "PEAKUP"
        elem.setAttributeNode rel
    XDoc.Save ThisWorkbook.Path & "yeni.xml"
End Sub

In addition to the information above, I want to share a few code blocks that can be used to Import Data from an XML file, Search and Delete.

To list all the data in the XML file:

Sub XML_Dosyasını_Okuma()
    Dim Etf As Object, ayır() As String, i As Integer
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    If Etf.Load(ThisWorkbook.Path & "etf.xml") Then
        ayır = Split(Etf.Text, " ")
        For i = 0 To UBound(ayır)
            Cells(i + 1, 1) = ayır(i)
        Next i
    End If
    Set Etf = Nothing: Erase ayır: i = Empty
End Sub

To list all the data in the management Node in the XML file:

DefObj I, N, R
Sub XML_Dosyasından_Veri_Alma()
    Dim i As Integer
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    Etf.Load (ThisWorkbook.Path & "etf.xml")
    Set Nod = Etf.SelectNodes("//yonetim/*")
    For Each Item In Nod
        i = i + 1
        Cells(i, 1) = Item.Text
    Next Item
    Set Etf = Nothing: Set Nod = Nothing
    Set Item = Nothing: i = Empty
End Sub

To list the information of the person named Murat in the management Node in XML file:

DefObj I, N, R
Sub XML_Dosyasından_Veri_Alma()
    Dim i As Integer
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    Etf.Load (ThisWorkbook.Path & "etf.xml")
    Set Nod = Etf.SelectNodes("//yonetim[ad='Murat']")
    For Each Item In Nod
        i = i + 1
        Cells(i, 1) = Item.Text
    Next Item
    Set Etf = Nothing: Set Nod = Nothing
    Set Item = Nothing: i = Empty
End Sub

To list the information of people whose City name is Istanbul in management node in XML file:

DefObj I, N, R
Sub XML_Dosyasından_Veri_Alma()
    Dim i As Integer
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    Etf.Load (ThisWorkbook.Path & "etf.xml")
    Set Nod = Etf.SelectNodes("//yonetim[sehir='Istanbul']")
    For Each Item In Nod
        i = i + 1
        Cells(i, 1) = Item.Text
    Next Item
    Set Etf = Nothing: Set Nod = Nothing
    Set Item = Nothing: i = Empty
End Sub

To list the information of the person named Emre with the SelectsingleNode method in management node in XML file:

DefObj I, N, R
Sub XML_Dosyasından_Veri_Alma()
    Dim i As Integer
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    Etf.Load (ThisWorkbook.Path & "etf.xml")
    Set Nod = Etf.SelectSingleNode("//yonetim[ad='Emre']")
    Range("A1").Value = Nod.Text
    Set Etf = Nothing: Set Nod = Nothing
    Set Item = Nothing: i = Empty
End Sub

To remove “Murat OSMA” in the site_management group from the list and save as new.xml  in the management node in XML file:(you can write on the old file too).

DefObj I, N, R
Sub Nod_Silme()
    Set Etf = CreateObject("MSXML2.DOMDocument")
    Etf.async = False
    Etf.Load (ThisWorkbook.Path & "etf.xml")
    Set Nod = Etf.SelectNodes("//yonetim[ad='Murat']")
    For Each Item In Nod
        Item.ParentNode.RemoveChild Item
    Next Item
    Etf.Save ThisWorkbook.Path & "yeni.xml"
End Sub

You can check Microsoft Docs for more details.

See you in other articles, bye. 🙋🏻‍♂️
You can share this post with your friends and get them informed as well.👍🏻

December 26 2011, 09:26

Полезная вводная статья о том, как загружать XML в Excel-VBA:
A Beginner’s Guide to the XML DOM

P.S. А это — еще одна статья на форуме, в дополнение к первой:
VBA. Импорт XML в Excel

Результатом стала простая тестовая программа в духе Hello world:

Sub Main()

Dim xmlDoc As MSXML2.DOMDocument
Dim xmlNodes As IXMLDOMNodeList
Dim xmlNode As IXMLDOMNode

Set xmlDoc = New MSXML2.DOMDocument
Dim source
source = ThisWorkbook.Path & "test.xml"
resp = xmlDoc.Load(source)
If Not resp Then
    cdd = xmlDoc.parseError.ErrorCode
    rsn = xmlDoc.parseError.reason
    lnn = xmlDoc.parseError.Line
    pss = xmlDoc.parseError.linepos
    src = xmlDoc.parseError.srcText
    MsgBox cdd & " | " & rsn & " | " & lnn & " | " & pss & " | " & src
Else
    Set xmlNodes = xmlDoc.SelectNodes("//child")
    For Each xmlNode In xmlNodes
        MsgBox xmlNode.Text
    Next
End If


End Sub

Файл «test.xml»:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <child>Hello, world!</child>
</root>

Данная программа реализована на VBA. Чтобы она заработала, не забудьте подключить библиотеку MSXML2. Для этого в редакторе MS VBA выберите Tools > References и найдите в списке Microsoft XML, v.5.0. Отметьте строку галочкой, нажмите ОК.

  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.

Понравилась статья? Поделить с друзьями:
  • Dokument microsoft office word docx
  • Doing word crossword clue
  • Doing things over and over word
  • Doing the word dance
  • Doing the same thing every day word