VBScript для AE - чтение XLS без Excel и запись красивого XML

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128
До недавнего времени пользовался для конвертации xls файлов Excel на сервере.
Порядок был такой:
был написан VBA скрипт, положен отдельно в формате .bas. Скрипт выдавал на выходе XML файл нужной структуры. Данные брались из самого xls файла + из внешнего xls файла SQL запросом. Потом скрипт модернизаровал и внешний xls файл заменился БД MySQL (на базе OpenServer)
VBS скрипт на сервере, брал входящий xls файл, внедрял в него скрипт (bas файл) и запускал.

Было куча глюков и прочих неудобных вещей изза запуска Excel на сервере. В случае ошибки, приходилось лезть на сервер, убивать процесс...

Сегодня переписал скрипт по обработке XLS файлов без использования Excel.
Привожу пример кода. Максимально описал и расписал.

Код:
'05 сентября 2019
'Доманский Александр
'Скрипт для парсинга XLS файла без участия Excel
'Плюс чтение данных из MySQL
'Запись XML файла на выходе
Function Main(inputs, outputFolder, params)

Dim inputFile, outputFile
'Из БД'
Dim Distorsia, Zub,
'Из XLS'
Dim JobNamber, CustomerName, CutTools

'адрес и имя первого входящего файла
inputFile = inputs(0)

'Название файла берется из первого значение списка параметров тикета Run Script
outputFile = outputFolder & "\" & params(0)

WScript.Echo inputFile
'WScript.Echo outputFile

'Читаем данные из XLS файла
Dim connStr, objConn, getNames
connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & inputFile & ";Extended Properties=""Excel 12.0 xml;HDR=No;IMEX=2;"";"

Set objConn = CreateObject("ADODB.Connection")
'Open Connection
objConn.open connStr

'Define recordset and SQL query
'тут мы через SQL запрос вытаскиваем данные из ИМЕННЫХ ячеек экселевского файла. Всё это в массив
Set rs = objConn.execute("SELECT * FROM JobNamber,CustomerName,CutTools")

'присваиваем значения переменным из массива
DO WHILE NOT rs.EOF
JobNamber = rs.Fields(0)
CustomerName = rs.Fields(1)
CutTools = rs.Fields(2)
rs.MoveNext
Loop


'Close connection XLS and release objects
objConn.Close
Set rs = Nothing
Set objConn = Nothing

' подключиться к БД:
' зная значение переменной CutTools из xls файла, получаем остальные данные из MySQL
Dim Connection, ConnectString, Sql, rec
'база данных pprint ; таблица tools
ConnectString = "Driver={MySQL ODBC 3.51 Driver};Server=localhost;PORT=3306;Database=pprint;User=root;Password=;charset=utf8;Option=3;"
Set Connection = CreateObject("ADODB.Connection")

Connection.Open ConnectString
' запрос к MySQL. Результат в массив.
Sql = "SELECT * FROM tools  WHERE IDCUT= '" & CutTools & "'"
Set rec = Connection.Execute(Sql)

    With rec
    'записываем данные из запроса в переменные.
    'Все запятые переводим в точки.
    Zub = .Fields("zub").Value
    Distorsia = Replace(.Fields("HDist").Value, ",", ".")
    End With
   
'Закрываем соединение с БД
Connection.Close


'формируем XML
Dim  rootNode, subNode, xmlDoc, commentItem, Fragment
Set xmlDoc = CreateObject("Msxml2.DOMDocument")
'Создание объявления XML
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version='1.0' encoding='utf-8'"))

'Создание корневого элемента
Set rootNode = xmlDoc.CreateElement("JOBS")
xmlDoc.AppendChild rootNode

Set subNode = rootNode.appendChild(xmlDoc.createElement("JobNamber"))
subNode.text = JobNamber

Set subNode = rootNode.appendChild(xmlDoc.createElement("CustomerName"))
subNode.text = CustomerName

Set subNode = rootNode.appendChild(xmlDoc.createElement("CutTools"))
subNode.text = CutTools

Set subNode = rootNode.appendChild(xmlDoc.createElement("Zub"))
subNode.text = Zub

Set subNode = rootNode.appendChild(xmlDoc.createElement("Distorsia"))
subNode.text = Distorsia


'* -- написание XML-файла с отступом для более легкого использования независимо от того, какая программа использовалась для просмотра или редактирования файла -- *'
Dim rdr, wrt, oStream
Set rdr = CreateObject("MSXML2.SAXXMLReader")
Set wrt = CreateObject("MSXML2.MXXMLWriter")

Set oStream = CreateObject("ADODB.STREAM")
oStream.Open
oStream.Charset = "UTF-8"

wrt.Indent = True
wrt.Encoding = "UTF-8"
wrt.Output = oStream
Set rdr.ContentHandler = wrt
Set rdr.ErrorHandler = wrt
rdr.Parse xmlDoc
wrt.Flush

'запись xml файла
oStream.SaveToFile outputFile, 2

Set rdr = Nothing
Set wrt = Nothing

Main = "OK"

End function

Dim inputs()
Dim outputFolder
Dim params()

Main inputs, outputFolder, params

Именованные ячейки:
121564


Имя файла XML на выходе в параметрах тикета
121565


XLS файл

П.С.
Библиотека ACE.OLEDB у меня х64
Потому в настройках Run Script стоит тип скрипта для х64.
 
  • Спасибо
Реакции: Fragarach и ACTPOHOM

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128
Забыл указать.
Библиотека MSXML2.MXXMLWriter
Напрочь обрезает комменты в XML файле.
Может кто подскажет как это исправить?
 

baraka

Участник
Сообщения
193
Реакции
90
До недавнего времени пользовался для конвертации xls файлов Excel на сервере.
Порядок был такой:
был написан VBA скрипт, положен отдельно в формате .bas. Скрипт выдавал на выходе XML файл нужной структуры. Данные брались из самого xls файла + из внешнего xls файла SQL запросом. Потом скрипт модернизаровал и внешний xls файл заменился БД MySQL (на базе OpenServer)
VBS скрипт на сервере, брал входящий xls файл, внедрял в него скрипт (bas файл) и запускал.

Было куча глюков и прочих неудобных вещей изза запуска Excel на сервере. В случае ошибки, приходилось лезть на сервер, убивать процесс...

Сегодня переписал скрипт по обработке XLS файлов без использования Excel.
Привожу пример кода. Максимально описал и расписал.

Код:
'05 сентября 2019
'Доманский Александр
'Скрипт для парсинга XLS файла без участия Excel
'Плюс чтение данных из MySQL
'Запись XML файла на выходе
Function Main(inputs, outputFolder, params)

Dim inputFile, outputFile
'Из БД'
Dim Distorsia, Zub,
'Из XLS'
Dim JobNamber, CustomerName, CutTools

'адрес и имя первого входящего файла
inputFile = inputs(0)

'Название файла берется из первого значение списка параметров тикета Run Script
outputFile = outputFolder & "\" & params(0)

WScript.Echo inputFile
'WScript.Echo outputFile

'Читаем данные из XLS файла
Dim connStr, objConn, getNames
connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & inputFile & ";Extended Properties=""Excel 12.0 xml;HDR=No;IMEX=2;"";"

Set objConn = CreateObject("ADODB.Connection")
'Open Connection
objConn.open connStr

'Define recordset and SQL query
'тут мы через SQL запрос вытаскиваем данные из ИМЕННЫХ ячеек экселевского файла. Всё это в массив
Set rs = objConn.execute("SELECT * FROM JobNamber,CustomerName,CutTools")

'присваиваем значения переменным из массива
DO WHILE NOT rs.EOF
JobNamber = rs.Fields(0)
CustomerName = rs.Fields(1)
CutTools = rs.Fields(2)
rs.MoveNext
Loop


'Close connection XLS and release objects
objConn.Close
Set rs = Nothing
Set objConn = Nothing

' подключиться к БД:
' зная значение переменной CutTools из xls файла, получаем остальные данные из MySQL
Dim Connection, ConnectString, Sql, rec
'база данных pprint ; таблица tools
ConnectString = "Driver={MySQL ODBC 3.51 Driver};Server=localhost;PORT=3306;Database=pprint;User=root;Password=;charset=utf8;Option=3;"
Set Connection = CreateObject("ADODB.Connection")

Connection.Open ConnectString
' запрос к MySQL. Результат в массив.
Sql = "SELECT * FROM tools  WHERE IDCUT= '" & CutTools & "'"
Set rec = Connection.Execute(Sql)

    With rec
    'записываем данные из запроса в переменные.
    'Все запятые переводим в точки.
    Zub = .Fields("zub").Value
    Distorsia = Replace(.Fields("HDist").Value, ",", ".")
    End With
  
'Закрываем соединение с БД
Connection.Close


'формируем XML
Dim  rootNode, subNode, xmlDoc, commentItem, Fragment
Set xmlDoc = CreateObject("Msxml2.DOMDocument")
'Создание объявления XML
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version='1.0' encoding='utf-8'"))

'Создание корневого элемента
Set rootNode = xmlDoc.CreateElement("JOBS")
xmlDoc.AppendChild rootNode

Set subNode = rootNode.appendChild(xmlDoc.createElement("JobNamber"))
subNode.text = JobNamber

Set subNode = rootNode.appendChild(xmlDoc.createElement("CustomerName"))
subNode.text = CustomerName

Set subNode = rootNode.appendChild(xmlDoc.createElement("CutTools"))
subNode.text = CutTools

Set subNode = rootNode.appendChild(xmlDoc.createElement("Zub"))
subNode.text = Zub

Set subNode = rootNode.appendChild(xmlDoc.createElement("Distorsia"))
subNode.text = Distorsia


'* -- написание XML-файла с отступом для более легкого использования независимо от того, какая программа использовалась для просмотра или редактирования файла -- *'
Dim rdr, wrt, oStream
Set rdr = CreateObject("MSXML2.SAXXMLReader")
Set wrt = CreateObject("MSXML2.MXXMLWriter")

Set oStream = CreateObject("ADODB.STREAM")
oStream.Open
oStream.Charset = "UTF-8"

wrt.Indent = True
wrt.Encoding = "UTF-8"
wrt.Output = oStream
Set rdr.ContentHandler = wrt
Set rdr.ErrorHandler = wrt
rdr.Parse xmlDoc
wrt.Flush

'запись xml файла
oStream.SaveToFile outputFile, 2

Set rdr = Nothing
Set wrt = Nothing

Main = "OK"

End function

Dim inputs()
Dim outputFolder
Dim params()

Main inputs, outputFolder, params

Именованные ячейки:
Посмотреть вложение 121564

Имя файла XML на выходе в параметрах тикета
Посмотреть вложение 121565

XLS файл

П.С.
Библиотека ACE.OLEDB у меня х64
Потому в настройках Run Script стоит тип скрипта для х64.

Ты всё равно используешь эксель и постоянно дёргаешь его библиотеки. Открою тебе большую тайну, это можно делать вообще не имея установленного экселя рядом с ран скриптером, а используя только java.
121577
 
  • Спасибо
Реакции: ACTPOHOM

baraka

Участник
Сообщения
193
Реакции
90
И да, у ран скриптера есть одна небольшая особенность, он не умеет выполнять больше одной задачи одновременно. То есть если у тебя на входе будет больше сотни файлов, у тебя AE на какой-то момент времени умрет. В добавок если будет какая нибудь ошибка, а они бывают выскакивают даже на самых простых сриптах из 4 строк (внезапно), у тебя так же все остальные задачи Run Script тупо встанут.
 

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128
И да, у ран скриптера есть одна небольшая особенность, он не умеет выполнять больше одной задачи одновременно. То есть если у тебя на входе будет больше сотни файлов, у тебя AE на какой-то момент времени умрет. В добавок если будет какая нибудь ошибка, а они бывают выскакивают даже на самых простых сриптах из 4 строк (внезапно), у тебя так же все остальные задачи Run Script тупо встанут.
Согласен. Но это скорее всего если идёт связка с WEB приложением, и пипл скидывает файлы в АЕ через web интерфейс. Тут пипла может быть много.
Я знаю как кастумную библиотеку подсунуть АЕ. Тему эту уже поднимали.
Моих знаний по Java не хватает, что бы своё написать свою библиотеку или использовать готовую. Максимум - "Привет мир!" )

Твой XML не шибко удобен.
Как ты мог заметить, я принципиально использую именные ячейки в экселе. Этим, я не привязываю ячейку к её координате.
В самом начале я делал как ты. Адрес ячейки = колонка : столбец.
Потом намучился, когда пришлось пару раз экселевский файл перевёрстывать, и соответственно перевёрстывать код скрипта.
Сейчас использую именные ячейки, и независиму от того, куда я переместил ячейку на странице, код править не требуется!

Для большинства задач, подойдёт и ранскриптер. Свой пример я выложил как основу, с чего можно начать.
Согласись, не у каждого в конторе есть в штате Java-программер. Зато с PHP/VBA/VBS/JS, может и сисадмин разобраться.
Ну или препрессер )
 

baraka

Участник
Сообщения
193
Реакции
90
файлы в АЕ через web интерфейс
Да так же могут через горячую папку закидывать

Твой XML не шибко удобен.
Он для других задач делался, можно так же передалать в аналогии как сделал ты

Для большинства задач, подойдёт и ранскриптер. Свой пример я выложил как основу, с чего можно начать.
Согласись, не у каждого в конторе есть в штате Java-программер.

Ты меня не понял, просто в заголовке надпись "без Execl", а по факту оказывается он нужен. Ну как минимум его бибилиотеки.
 

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128
Да, нужна библиотека. Она бесплатна. Скачивается с сайта Майкрасофта.
Я эту тему "нарыл" на форуме 1С-ников. Им экселевские файлы в 1С требуется забивать, без использования Экселя на сервере.

Для меня, в принципе и с Экселем не проблема. Но он не работает как сервис или т.п.
Приходится постоянно по DRP связь держать, иначе не открывается. Обойти это не вышло.
Зато с библиотекой всё красиво.
Правда запросы в SQL формате. И я пока в ступоре как обход таблицы с неизвестным кол-вом строк сделать. Сформировав при этом xml.
Но это мелочи. 2-3 дня и сделается.


Кстати, раз уж вы серьезно подкованы в Java.
Мне, что бы подсунуть свой jar, и что бы АЕ его видела, требуется сервер (железо) перезагрузить. Рестарт АЕ не помогает.
Как вы с этим справляетесь? Не перезапускаете же каждый раз сервер?
 

baraka

Участник
Сообщения
193
Реакции
90
Мне, что бы подсунуть свой jar, и что бы АЕ его видела, требуется сервер (железо) перезагрузить. Рестарт АЕ не помогает.
Как вы с этим справляетесь? Не перезапускаете же каждый раз сервер?

Я classpath редактирую через сервисную утилиту, подсовывую туда то что нужно и "net stop BGMD && net start BGMD"
 

baraka

Участник
Сообщения
193
Реакции
90
Сложновато. Я jar в /lib/ext кидал и перезагружал. classpath не трогал.
Ну скидывай, в чём вопрос :) Это до тех пор пока память на сервере не потечет, если библиотека большая понадобится.
Ты открой у себя диспечер задач на сервере и посмотри сколько jvm процессов висит, когда ты закидываешь в ext все jvm подгружают твою библиотеку. Поэтому я редактирую classpath только там где нужно.
 
  • Спасибо
Реакции: Spirit412

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128
Спасибо.
Скажи, а не проще ли при больших количествах xls/xlsx -> xml перегонять не в АЕ?
К примеру, используя решения на nodejs/PHP ?
В АЕ отправлять готовый XML.
 

ACTPOHOM

12 лет на форуме
Сообщения
2 981
Реакции
1 133
Ты всё равно используешь эксель и постоянно дёргаешь его библиотеки. Открою тебе большую тайну, это можно делать вообще не имея установленного экселя рядом с ран скриптером, а используя только java.
Посмотреть вложение 121577
а как быть с XlsX ? библиотека про его формат знает ?
 

Spirit412

Топикстартер
15 лет на форуме
Сообщения
870
Реакции
128

ACTPOHOM

12 лет на форуме
Сообщения
2 981
Реакции
1 133
Тема интересная для всех, так или иначе все сталкиваются с интеграцией Excel к АЕ способов достаточно много, жаль Эско не сделала штатную утилиту, о которой очень просят пользователи.
 

baraka

Участник
Сообщения
193
Реакции
90
Спасибо.
Скажи, а не проще ли при больших количествах xls/xlsx -> xml перегонять не в АЕ?
К примеру, используя решения на nodejs/PHP ?
В АЕ отправлять готовый XML.

Мне не проще, а так дело вкуса.

а как быть с XlsX ? библиотека про его формат знает ?

да
 
  • Спасибо
Реакции: ACTPOHOM

ACTPOHOM

12 лет на форуме
Сообщения
2 981
Реакции
1 133
А как ты перегружаешь "net stop BGMD && net start BGMD" ?
насколько я помню, если серверу сделаь Activate он гасит все службы и заново их запускает. 5 минут от силы все занимает
 

baraka

Участник
Сообщения
193
Реакции
90
А как ты перегружаешь "net stop BGMD && net start BGMD" ?
насколько я помню, если серверу сделаь Activate он гасит все службы и заново их запускает. 5 минут от силы все занимает

Кнопка Activate сделана для другого. Это проверка целостности конфигурационных файлов и внутренней базы nosql,sql. Не нажимай на неё без надобности.


Тема интересная для всех, так или иначе все сталкиваются с интеграцией Excel к АЕ способов достаточно много, жаль Эско не сделала штатную утилиту, о которой очень просят пользователи.

Да у господина Дроздова ролик как подружить AE с xls уже несколько лет висит. Речь тут про другое, когда у тебя данных много этот способ не подходит. Постоянное дёрганье экселевских библиотек, скрипт раннер со своими особенностями... Тебе Илья Фисюк так и ответил на эсковском форуме, зачем это нужно...
 
  • Спасибо
Реакции: ACTPOHOM

ACTPOHOM

12 лет на форуме
Сообщения
2 981
Реакции
1 133
Да, я про то же. Одно дело создание заказа по Excel а другое обработка потоком кучи файлов.
У меня работает система со скриптом под Excel, но мне не нравится, именно по причине неустойчивости скриптранера и самого Excel.