Доброго времени суток.
Столкнулся, значит, с такой проблемой. Есть обработка в 1С 8.2 и туда надо запихнуть в автоматическом режиме кучу данных. Куча данных находилась в своей базе данных, в своей архитектуре и подключить базу к 1С или переформатировать таблицы не представлялось возможным. Единственный способ, как мне показалось, вывести таблицу на виртуальный принтер, а оттуда и плясать начнем.
Итак, имеем документ в формате *.xps, который нам дал заботливый виртуальный принтер:
Собственно, из этого всего, мне нужны только строчки самой работы, строчки подработ (начинаются со знака "-") и колонка нормы времени для каждой работы. Сначала я подумал, что формат XPS графический и придется полученный файл загонять в любую OCR программу, там распознавать таблицу и сохранять данные в формате Excel. Сначала так и сделалось, но есть огромные минусы:
— нет автоматизации процесса при конвертировании XPS -> 1C.
— OCR программы могут накосячить в распознавании текста.
— процесс конвертации занимает много времени.
Поэтому пришлось разбираться с форматом XPS напрямую.
Собственно, как оказывается, формат XPS — это обычный ZIP-файл. Вся информация там находится в виде XML. Картинки идут картинками, текст текстом. Но нам-то текст и нужен…
Внутри имеем такую картину:
Не буду вдаваться в подробности и содержание каждой папки – там все просто, если интересно, то можно полазить и самому. Меня конкретно интересует только один файл:
.. Documents1FixedDocument.fdoc
Вот листинг этого файла:
<?xml version="1.0" encoding="UTF-8" ?>
- <FixedDocument xmlns="http://schemas.microsoft.com/xps/2005/06">
<PageContent Source="/Documents/1/Pages/1.fpage" />
<PageContent Source="/Documents/1/Pages/2.fpage" />
<PageContent Source="/Documents/1/Pages/3.fpage" />
<PageContent Source="/Documents/1/Pages/4.fpage" />
</FixedDocument>
Как видим, тут пути к файлам страниц документа.
Оформляем это все в код 1С:
Процедура ОсновныеДействияФормыВСправочник(Кнопка)
РежимДиалога = РежимДиалогаВыбораФайла.Открытие;
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалога);
ДиалогВыбора.МножественныйВыбор = Истина;
ДиалогВыбора.Фильтр = "XPS |*.xps";
Если ДиалогВыбора.Выбрать() Тогда
Количество = ДиалогВыбора.ВыбранныеФайлы.Количество();
Для Стр = 0 по Количество - 1 Цикл
ПолучитьДанныеХПС(ДиалогВыбора.ВыбранныеФайлы[Стр], ДиалогВыбора.Каталог);
ПерегнатьВСправочник();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Для начала разархивируем содержимое файла во временную папку:
Процедура ПолучитьДанныеХПС (Файл, Каталог)
КодМарки = СтрЗаменить(Файл, Каталог, "");
КодМарки = СтрЗаменить(КодМарки, ".xps", "");
СоздатьКаталог(Каталог + КодМарки);
ЗИПФайл = Новый ЧтениеZipФайла(Файл);
ЗИПФайл.ИзвлечьВсе(Каталог + КодМарки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
ЗИПФайл.Закрыть();
Теперь в директории файла имеем все возможности для работы. Нас интересует, как писалось выше, список файлов со страницами. Перегружаем список в таблицу. Работаем с этим файлом как с обычным XML:
ФайлХПС = Новый ЧтениеXML;
ФайлХПС.ОткрытьФайл(Каталог + КодМарки + "Documents1FixedDocument.fdoc");
ПутьКФайлу.Очистить();
Нормочасы.Очистить();
Пока ФайлХПС.Прочитать() Цикл
ФайлХПС.ПрочитатьАтрибут();
Если ПроверитьЗначение(ФайлХПС.Значение) Тогда
ЭлементыФормы.ПутьКФайлу.ДобавитьСтроку();
ЭлементыФормы.ПутьКФайлу.ТекущаяСтрока.Путь = ФайлХПС.Значение;
КонецЕсли;
КонецЦикла;
ФайлХПС.Закрыть();
Все, имеем список файлов. Теперь приступаем к самим файлам. Файл страницы сам текстовый, но правила написания не XML. Структура блочная. Блоками отдельно пишется текстовая информация и графическая. Все блоки имеют координаты по оси Х и Y, для расположения на странице. Меня интересуют только текстовые блоки и их координаты, ну и их информация.
Блоки имеют начало и конец, понять где начало и конец просто: < />
В каждом блоке первое слово — его имя. Текстовые блоки имеют имя: Glyphs
Вот пример блока:
<Glyphs Fill="#ff000000" FontUri="/Documents/1/Resources/Fonts/DD1ED91D-300C-4E84-BACC-6412D0EB3F5F.odttf" FontRenderingEmSize="13.2795" StyleSimulations="None" OriginX="971.84" OriginY="59.68" Indices="19,55;26;17;19;21,55;17;21;19;20,55;24" UnicodeString="07.02.2015" />
Меня интересуют тут только параметры:
— OriginX, для определения колонок.
— UnicodeString как само значение того, что содержится в строке.
Читать придется как обычный текстовый файл. Текстовые блоки все пишутся одной строкой. В 1С можно прочитать строку до символа перевода коретки:
ФайлХПС = Новый ЧтениеТекста(Файл, КодировкаТекста.UTF8);
Стр = ФайлХПС.ПрочитатьСтроку();
Пока Стр <> Неопределено Цикл
СтруктураПараметров = ПроверитьИмяПараметра(Стр);
...
А полученную строку проверяем на параметр, если начинается на Glyphs, то берем на проверку и анализ, если нет — читаем следующий.
Придется строку анализировать побуквенно и переписывать в структуру.
Функция ВозвратитьРеквизитыПараметра(Строка)
Перем
ИмяПараметра, КоординатыПараметра;
ИмяПараметра = "";
КоординатыПараметра = "";
Кавычка = """";
СтруктураПараметров = Новый Структура;
Если Найти(Строка, "UnicodeString") > 0 Тогда
Для Х = Найти(Строка, "UnicodeString") + 15 по СтрДлина(Строка) Цикл
Буква = Сред(Строка, Х, 1);
Если Буква <> """" Тогда
ИмяПараметра = ИмяПараметра + Буква;
Иначе
СтруктураПараметров.Вставить("ИмяПараметра", ИмяПараметра);
КонецЕсли;
КонецЦикла;
Для Х = Найти(Строка, "OriginX") + 9 по СтрДлина(Строка) Цикл
Буква = Сред(Строка, Х, 1);
Если Буква <> Кавычка Тогда
КоординатыПараметра = КоординатыПараметра + Буква;
Иначе
СтруктураПараметров.Вставить("КоординатыПараметра", Число(КоординатыПараметра));
Возврат СтруктураПараметров;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат СтруктураПараметров;
КонецФункции
Собственно, по выполнении функции, имеем все для анализа. Имя параметра, его координаты, значение параметра. Блоки выводят текст в XPS сверху вниз и слева направо. По координатам Х можно определить колонки, по названию параметра можем проанализировать какая информация нам нужна, а какая нет. Дальше расписывать как оно все уходило в справочник 1С не буду — там и так все понятно. Главное, я получил ответ как быстро извлечь нужную информацию из «графического» файла.
Автор: yurickas