Перегружаем данные из XPS в обработку 1С без OCR

в 17:51, , рубрики: 1c 8.2, конвертация, Программирование, хранение данных

Доброго времени суток.

Столкнулся, значит, с такой проблемой. Есть обработка в 1С 8.2 и туда надо запихнуть в автоматическом режиме кучу данных. Куча данных находилась в своей базе данных, в своей архитектуре и подключить базу к 1С или переформатировать таблицы не представлялось возможным. Единственный способ, как мне показалось, вывести таблицу на виртуальный принтер, а оттуда и плясать начнем.

Итак, имеем документ в формате *.xps, который нам дал заботливый виртуальный принтер:

Перегружаем данные из XPS в обработку 1С без OCR - 1

Собственно, из этого всего, мне нужны только строчки самой работы, строчки подработ (начинаются со знака "-") и колонка нормы времени для каждой работы. Сначала я подумал, что формат XPS графический и придется полученный файл загонять в любую OCR программу, там распознавать таблицу и сохранять данные в формате Excel. Сначала так и сделалось, но есть огромные минусы:

— нет автоматизации процесса при конвертировании XPS -> 1C.
— OCR программы могут накосячить в распознавании текста.
— процесс конвертации занимает много времени.

Поэтому пришлось разбираться с форматом XPS напрямую.

Собственно, как оказывается, формат XPS — это обычный ZIP-файл. Вся информация там находится в виде XML. Картинки идут картинками, текст текстом. Но нам-то текст и нужен…

Внутри имеем такую картину:

Перегружаем данные из XPS в обработку 1С без OCR - 2

Не буду вдаваться в подробности и содержание каждой папки – там все просто, если интересно, то можно полазить и самому. Меня конкретно интересует только один файл:
.. 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js