llever Пользователь Сообщений: 13 |
#1 25.02.2019 20:21:02 Здравствуйте, возникла необходимость конвертации данных из таблицы Excel в XML по схеме (схему приложил), перечитал много информации, понял что реально это сделать макросом, в интернете нашел пример макроса конвертации, попытался переделать макрос под выгрузку моих данных из Excel в XML чтоб выгрузка соответствовала моей схеме XML. Но что-то я видимо не совсем так делаю…
Прикрепленные файлы
|
||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
Доброе время суток. |
llever Пользователь Сообщений: 13 |
#3 26.02.2019 12:45:50 Огромное спасибо! Работает как и нужно было.
|
||
llever Пользователь Сообщений: 13 |
Прикрепил файлы, т.к. в предыдущем сообщении забыл это сделать. Изменено: llever — 26.02.2019 14:09:42 |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#5 26.02.2019 13:34:15
Получаете текст xmlDoc.XML заменяете табуляцию на два пробела, грузите текст xmlDoc.loadXML |
||
llever Пользователь Сообщений: 13 |
Большое спасибо за помощь! |
Georgii Пользователь Сообщений: 1 |
#7 16.09.2020 21:37:32
Здравствуйте! Очень помог этот метод, уже было почти адаптировал под свою задачу. Но не могу справиться с использованием пространства имён, причём в определённой иерархии — прикрепил результат, которого пытаюсь добиться. Прикрепленные файлы
|
||
Максим Пользователь Сообщений: 268 |
#8 27.10.2022 15:53:09 Андрей VG, за
ничего непонятно, но работает прекрасно — магия) |
|
Краткая справка:
Microsoft Excel — Программа для работы с электронными таблицами. Она предоставляет возможности экономико-статистических расчетов, графические инструменты и язык макропрограммирования VBA (Visual Basic for Application).
Visual Basic for Applications (VBA, Visual Basic для приложений) — немного упрощённая реализация языка программирования Visual Basic, встроенная в линейку продуктов Microsoft Office, а также во многие другие программные пакеты.
XML(англ. eXtensible Markup Language — расширяемый язык разметки). XML — язык с простым формальным синтаксисом, удобный для создания и обработки документов программами и одновременно удобный для чтения и создания документов человеком. Разработчик волен создать разметку в соответствии с потребностями к конкретной области, будучи ограниченным лишь синтаксическими правилами языка.
Задача:
Экспортировать данные из таблицы Excel и сформировать XML-файл с заданной структурой для последующей обработки сторонними программными продуктами.
Исходная таблица с некоторыми данными:
Код VBA:
Sub exportXML() 'Путь для сохранения итогового XML xmlFile = ActiveWorkbook.Path & "export.xml" 'Строка и столбец расположения названия компании Dim company_row As Integer company_row = 1 Dim company_col As Integer company_col = 1 'Номер строки начала таблицы с данными Dim data_row As Integer data_row = 3 'Номер столбца "Порядковый номер" Dim num_col As Integer num_col = 1 'Номер столбца "ФИО" Dim name_col As Integer name_col = 2 'Номер столбца "Профессия" Dim profession_col As Integer profession_col = 3 'Номер столбца "Наличность" Dim profit_col As Integer profit_col = 4 'Cоздание объекта XML Set xml = CreateObject("MSXML2.DOMDocument") 'Добавление описания XML xml.appendChild xml.createProcessingInstruction("xml", "version='1.0' encoding='utf-8'") 'Добавление корневого элемента "company" Set Company = xml.createElement("company") 'Добавление атрибута "name" Company.setAttribute "name", Cells(company_row, company_col) xml.appendChild (Company) 'Цикл по строкам (пока не встретится строка с пустым "Порядковым номером") Do While Not IsEmpty(Cells(data_row, num_col)) 'Вызов функции добавления сотрудника компании Company.appendChild (createPerson(xml, Cells(data_row, num_col), _ Cells(data_row, name_col), _ Cells(data_row, profession_col), _ Cells(data_row, profit_col))) 'Переход к следующей строке таблицы data_row = data_row + 1 Loop 'Выполнение XSL-преобразования для добавления отступов в XML Call transformXML(xml) 'Сохранение файла (без выбора пути сохранения, удобно при отладке) 'xml.Save xmlFile 'MsgBox "Export complete!" 'Сохранение файла (с выбором пути сохранения) xml.Save Application.GetSaveAsFilename("", "Файл экспорта (*.xml),", , "Введите имя файла", "Сохранить") End Sub 'Функция добавления сотрудника компании(xml, "Порядковый номер", "ФИО", "Профессия", "Наличность") возвращает узел XML Function createPerson(ByRef xml As Variant, ByVal num As Variant, ByVal name As Variant, _ ByVal profession As Variant, ByVal profit As Variant) As Variant 'Создание элемента person Set createPerson = xml.createElement("person") createPerson.setAttribute "num", num 'Добавление в виде комментария "Профессия" (просто для примера) createPerson.appendChild (xml.createComment(profession)) 'Создание элементов для столбцов "ФИО" и "Наличность" createPerson.appendChild(xml.createElement("name")).Text = name createPerson.appendChild(xml.createElement("profit")).Text = profit End Function 'Процедура для придания XML читабельного вида (с отступами) Sub transformXML(ByRef xml As Variant) 'Cоздание объекта XSL Set xsl = CreateObject("MSXML2.DOMDocument") 'Загрузка XSL из строки (не требует наличия отдельного XSL-файла) xsl.LoadXML ("<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" & vbCrLf & _ "<xsl:output method='xml' version='1.0' encoding='UTF-8' indent='yes'/>" & vbCrLf & _ "<xsl:template match='@*|node()'>" & vbCrLf & _ "<xsl:copy>" & vbCrLf & _ "<xsl:apply-templates select='@*|node()' />" & vbCrLf & _ "</xsl:copy>" & vbCrLf & _ "</xsl:template>" & vbCrLf & _ "</xsl:stylesheet>") 'Выполнение преобразования xml.transformNodeToObject xsl, xml End Sub
Результат в виде XML:
<?xml version="1.0" encoding="UTF-8"?> <company name="ООО 'Рога и копыта'"> <person num="1"> <!--Великий комбинатор--> <name>Остап Ибрагимович Бендер</name> <profit>225000</profit> </person> <person num="2"> <!--Нарушитель конвенции--> <name>Михаил Самуэлевич Паниковский</name> <profit>30000</profit> </person> <person num="3"> <!--Водитель автомобиля «Антилопа-Гну»--> <name>Адам Казимирович Козлевич</name> <profit>95000</profit> </person> <person num="4"> <!--Подпольный миллионер--> <name>Александр Иванович Корейко</name> <profit>1000000</profit> </person> <person num="5"> <!--Сын лейтенанта Шмидта--> <name>Шура Балаганов</name> <profit>50000</profit> </person> </company>
30.07.2015/
https://skynet48.ru/wp-content/uploads/2015/08/Advanced-Excel-VBA-Macros.png
283
343
admin
https://skynet48.ru/wp-content/uploads/2017/04/logo_skynet.png
admin2015-07-30 16:43:312018-06-20 11:41:49Экспорт из Excel в XML с помощью макроса на VBA
- Работа с файлами XML
- Массивы
Функция Array2XML формирует из исходной таблицы объект типа DOMDocument, который можно выгрузить в XML-файл одной строкой кода (метод Save)
Sub XMLExport() Dim Заголовок As Range, Данные As Range Set Заголовок = Range("a1:f1") Set Данные = Range([A2], Range("A" & Rows.Count).End(xlUp)).Resize(, Заголовок.Columns.Count) arrHeaders = Application.Transpose(Application.Transpose(Заголовок.Value)) ПутьКФайлуXML = ThisWorkbook.Path & "result.xml" ' формируем DOMDocument, и сохраняем XML в файл result.xml Array2XML(Данные.Value, arrHeaders, "Root").Save ПутьКФайлуXML If Err = 0 Then MsgBox "Создан XML файл" & vbNewLine & ПутьКФайлуXML, vbInformation, "Готово" End Sub
Код функции Array2XML:
Function Array2XML(ByVal arrData, ByVal arrHeaders, ByVal strHeading$) As DOMDocument ' получает в качестве параметров: ' двумерный массив arrData с данными для выгрузки, ' одномерный массив arrHeaders, содержащий заголовки столбцов, ' и strHeading$ - XML-константу объекта Dim xmlDoc As DOMDocument, xmlFields As IXMLDOMElement, xmlField As IXMLDOMElement Set xmlDoc = CreateObject("Microsoft.XMLDOM") ' создаём новый DOMDocument DataColumnsCount% = UBound(arrData, 2) - LBound(arrData, 2) + 1 HeadersCount% = UBound(arrHeaders) - LBound(arrHeaders) + 1 If DataColumnsCount% <> HeadersCount% Then MsgBox "Количество заголовков в массиве arrHeaders" & _ "не соответствует количеству столбцов массива", vbCritical, "Ошибка создания XML": End xmlDoc.loadXML Replace("<" + strHeading + "/>", " ", "_") ' записываем XML-константу объекта For i = LBound(arrData) To UBound(arrData) ' создание нового узла Set xmlFields = xmlDoc.documentElement.appendChild(xmlDoc.createElement("Row")) For j = LBound(arrHeaders) To UBound(arrHeaders) ' добавление полей в узел Set xmlField = xmlFields.appendChild(xmlDoc.createElement(Replace(arrHeaders(j), " ", "_"))) xmlField.Text = arrData(i, j + LBound(arrData, 2) - LBound(arrHeaders)) Next j Next i Set Array2XML = xmlDoc End Function
Функция нашла применение в программе выгрузки тарифов в XML
- 27844 просмотра
Не получается применить макрос? Не удаётся изменить код под свои нужды?
Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.
- Download source files — 3.33 KB
- Download demo project — 47.41 KB
Introduction
In Excel XP, there is a new export option for XML. However, what I get is many rubbish tags (I’m so disappointed…). Then, after searching on the Google (our nice search engine) for some time about «Converting Excel to XML», what I get are conversion tools that simply make a Rational table to XML. However, what I want is the support of nested structures (e.g. <data><field1>....</field1><data>
). As a result, I decided to write my own using VBA… (don’t ask me why VBA… may be I will port it to my favorite C++ platform later.
Using the Code
The source code contains 2 functions GenerateXMLDOM()
and fGenerateXML()
. They are actually doing the same thing in a different approach.
GenerateXMLDOM
— Gives a Microsoft XMLDOM
object which you can play with or serialize into an XML at any time using the «Save
» method.
fGenerateXML
— Generates a long string which is ready for output as file (more readable, as proper newline is added).
Both functions have the same parameters. The first one is rngData
, which is the selected table area in the Excel Sheet for conversion. The second (rootNodeName
) is the first/root node’s name used in the XML.
In the selected range, the first row is expected to be the field (or node) names. One thing that is worth noticing is that we can use the node name to define the level it belongs to. Started and separated by the node delimiter «/», the node name is one level deeper than the previous one. e.g. /data/field1 is equivalent to <data><field1>....</field1><data>
, /student/name/surname is equivalent to <student><name><surname>.... </surname></name></student>
:
Function GenerateXMLDOM(rngData As Range, rootNodeName As String) ... Function fGenerateXML(rngData As Range, rootNodeName As String) As String ...
Limitation and Notes
The ordering of fields may affect the generated XML, fields that have to be placed inside the same sub-node should be placed next to each other. For example, if /student/id and /student/name are placed next to each other, it will generate:
<student><id>..</id><name>...</name></student>
However, if not, the result will be:
<student><id>..</id></student> <somebrabra...> ... </somebrabra...> <student><name>..</name></student>
The reason is that it only checks with the last field instead of all before deciding where the node should be created.
Finally I would like to thank Hasler Thomas, the author of A Filebrowser for VBA, who provided the code for file browse. Hope this code will be useful for you. Please let me know if there are any bugs.
History
- 4 May 2004 — First release 0.8 version
0 / 0 / 0 Регистрация: 27.02.2012 Сообщений: 21 |
|
1 |
|
15.01.2014, 07:13. Показов 25260. Ответов 8
Добрый день. Есть такая задача:
Пример файла во вложении
0 |
Surrogate Ушел с CyberForum совсем! 873 / 182 / 25 Регистрация: 04.05.2011 Сообщений: 1,020 Записей в блоге: 110 |
||||||||||||
15.01.2014, 11:13 |
2 |
|||||||||||
Есть xml файл в котором есть перечень сотрудников. Нужно циклом из этого файла фамилию каждого сотрудника выгрузить в отдельную ячейку в екселе. Как сделать это макросом файл xml отрывается ровно также как книги экселя
В приложенном файле фамилии хранятся в 10-ом столбце, их значения в целевой файл можно считывать так
Как сделать цикл, чтобы он сканировал xml файл до самой последней строки, так как не известно сколько сотрудников будет в нем указано. тело таблицы начинается с третьей строки, для определения общего количества строк можно использовать цикл
Добавлено через 2 минуты
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 |
А представьте около 10000 cm файлов. Надо каждый так загружать? ))) 10000 cm ? это как
хах, решение нашел в чем секрет, если не секрет ?
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 |
В вашем решении я как понимаю каждую 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 |
|||
Их Оооочень много вчера в этой ветке помогали человеку исправить 150 книг эксель Добавлено через 24 минуты
Добавлено через 34 минуты
В любом случае спасибо вам за помощь. Вы единственный откликнулись Не единственный, ведь код с DOMDocument тебе на другом форуме присоветовали
0 |
72 / 0 / 0 Регистрация: 19.06.2014 Сообщений: 68 |
|
16.03.2016, 11:32 |
9 |
Добрый день.
0 |