Общее·количество·просмотров·страницы

четверг, 15 ноября 2012 г.

XML в 1С


При любом внедрении 1С на действующем предприятии, первоочередной становится задача по переносу данных в новую программу. Платформа предоставляет несколько возможностей для этого: DBF, XML, COM соединение, OLE. В этом посте я остановлюсь на XML, из основных преимуществ данного подхода это универсальность (данные могут быть выгружены из различных программ), относительно более быстрая скорость обработки, по сравнению скажем с DBF, возможность полного переноса документа, справочника и т. п. в другую базу (стоит упомянуть, что это более менее корректно работает с одинаковыми конфигурациями в ином случаи придется «допиливать»).
Процитирую википедию.
XML — это описанная в текстовом формате иерархическая структура, предназначенная для хранения любых данных. Визуально структура может быть представлена как дерево элементов. Элементы XML описываются тегами.
Т.е. Документы, справочники и другие объекты конфигурации могут быть представлены в виде структуры: <Сотрудник Код="0000000136" ВидЗанятости="ОсновноеМестоРаботы" ВидДоговора="ТрудовойДоговор">Зыбченко Алексей Александрович</Сотрудник>
данная строка состоит из атрибутов: Код, ВидЗанятости, у каждого атрибута свое значение в качестве текста в строке использовано ФИО сотрудника, но мы можем обойтись и без текста, просто переместив ФИО сотрудника в атрибут. Для считывания/записи атрибутов, текстов, узлов в платформе 1С предусмотрены специальные функции.
Стоит сказать еще пару слов о структуре. Структура всего XML документа представлет из себя следующее (рис. 1).

В документе обязательно должен присутствовать корневой узел, в который входят остальные узлы. Порядок обхода следующий, получаем значение 1 узла, проходим все его атрибуты и идем к следующему узлу, т. е. осуществляем последовательный обход все узлов. Разберем кое что на примерах.
Перенос документа из одной базы в другую.
Выполним выгрузку следующей обработкой:
ЗаписьXML = Новый ЗаписьXML(); //Создадим объект класса XML
ЗаписьXML.ОткрытьФайл(«c:\doc.xml»); //Если файла нет то он будет автоматически создан, если существует то будет перезаписан
ЗаписьXML.ЗаписатьНачалоЭлемента(«Root»); //записываем корневой элемент
ВыгружаемыйОбъект = Документ.ПолучитьОбъект();
ЗаписатьXML(ЗаписьXML, ВыгружаемыйОбъект); //Записываем нащ док в XML
ЗаписьXML.ЗаписатьКонецЭлемента(); //Конец узла Root
ЗаписьXML.Закрыть(); //Ну и записываем

Для загрузки код такой:
ЧтениеXML = Новый ЧтениеXML(); //Создаем объект из класса ЧтениеXML
ЧтениеXML.ОткрытьФайл(«c:\doc.xml»); //Открываем файл
ЧтениеXML.Прочитать(); //Эта функция чаще всего выполняется в цикле, здесь мы прочитали узел Root
ЧтениеXML.Прочитать(); //Переходим к узлу с документом
Если ВозможностьЧтенияXML(ЧтениеXML) Тогда //Проверяем соответствует ли тип в документе тип данных в платформе
ЗагружаемыйОбъект = ПрочитатьXML(ЧтениеXML); //Считывает данные
ЗагружаемыйОбъект.Записать(); //записываем наш документ
КонецЕсли;
ЧтениеXML.Закрыть();

Повторюсь данный метод хорошо работает только в одинаковой конфигурации.

Перенос произвольной структуры.
Чаще всего при переносе данных, получается так что нельзя однозначно сопоставить выгруженный документ/справочник, решение проблемы заключается в выгрузке документа произвольной структуры.
Разберем опять на листинге. В примере мне был необходимо перенести справочник сотрудников, из ЗУП в УПП. Справочники Организации, ПодразделенияОрганизаций, ДолжностиОргаизаций, ФизическиеЛица уже заполнены. Новые сотрудники так же должны иметь одинаковый код. Листинг слегка сократил. Документ XML должен представлять из себя:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Сотрудник Код="0000000531" ФизлицоКод="0000000531" ПодразделениеОрганизацииКод="000000018">Зыбченко Алексей Александрович</Сотрудник>
</Root>

Присутствует корневой узел Root и узел Сотрудник с атрибутами Кода, ФизлицоКод, ПодразделениеОрганизацииКод, а ФИО использовал в качестве текста в теге.

Процедура Кнопка1Нажатие(Элемент) //Выгрузка сотр
//Делаем запрос к справочнику сотрудника
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СотрудникиОрганизаций.Код,
| СотрудникиОрганизаций.Наименование,
| СотрудникиОрганизаций.Физлицо.Код,
| СотрудникиОрганизаций.ПодразделениеОрганизации.Код,
|ИЗ
| Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций
|ГДЕ
| СотрудникиОрганизаций.ДатаУвольнения = &ДатаУвольнения";
Запрос.УстановитьПараметр("ДатаУвольнения", Дата("00010101"));
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Файл = Новый ЗаписьXML; //Создаем объект для записи XML
Файл.ОткрытьФайл("C:\temp\uploadsot.xml"); //Файл с данными
Файл.ЗаписатьОбъявлениеXML(); //Объявление обязательно!
Файл.ЗаписатьНачалоЭлемента("Root"); //Пишем корневой элемент
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл //В цикле выводим данные в XML
Файл.ЗаписатьНачалоЭлемента("Сотрудник");
Файл.ЗаписатьАтрибут("Код", ВыборкаДетальныеЗаписи.Код); // Записываем атрибут и его значение
Файл.ЗаписатьАтрибут("ФизлицоКод", ВыборкаДетальныеЗаписи.ФизлицоКод);
Файл.ЗаписатьАтрибут("ПодразделениеОрганизацииКод", ВыборкаДетальныеЗаписи.ПодразделениеОрганизацииКод); Файл.ЗаписатьТекст(ВыборкаДетальныеЗаписи.Наименование);
Файл.ЗаписатьКонецЭлемента();
КонецЦикла;
Файл.ЗаписатьКонецЭлемента();
Файл.Закрыть(); //Записываем файл
КонецПроцедуры

Процедура для загрузки. Листинг сокращен.

Процедура ЗагрузитьСотрудникиНажатие(Элемент)
Файл = Новый ЧтениеXML;
Файл.ОткрытьФайл("C:\temp\uploadsot.xml");
Пока Файл.Прочитать() Цикл //Проход по узлам
Если Файл.Имя <> "Сотрудник" Тогда //Не проходим узел Root
Продолжить;
КонецЕсли;
Если Файл.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
//Если начало элемента то читаем атрибуты в цикле
Пока Файл.ПрочитатьАтрибут() Цикл
Если Файл.Имя = "Код" Тогда //Проверяем имя узла
Код = Файл.Значение;
ИначеЕсли Файл.Имя = "ФизлицоКод" Тогда
ФизлицоКод = Файл.Значение;
ИначеЕсли Файл.Имя = "ПодразделениеОрганизацииКод" Тогда
ПодразделениеОрганизацииКод = Файл.Значение;
КонецЕсли;
КонецЦикла;
//Если в справочнике нет элемента то запишем его
Если НЕ ЗначениеЗаполнено(Справочники.СотрудникиОрганизаций.НайтиПоКоду(Код)) Тогда
Сотрудник = Справочники.СотрудникиОрганизаций.СоздатьЭлемент();
Сотрудник.Код = Код;
Сотрудник.Физлицо = Справочники.ФизическиеЛица.НайтиПоКоду(ФизлицоКод);
Сотрудник.ПодразделениеОрганизации = Справочники.ПодразделенияОрганизаций.НайтиПоКоду(ПодразделениеОрганизацииКод);
Если Файл.Прочитать() Тогда //Поскольку текст не атрибут а другой узел то перейдем к нему
//Проверяем тип узла и пишем
Если Файл.ТипУзла = ТипУзлаXML.Текст Тогда
Сотрудник.Наименование = Файл.Значение;
Сотрудник.Записать();
Иначе
Сообщить("Ошибка формата");
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Файл.Закрыть();
КонецПроцедуры

У XML свои плюсы и минусы но если нужно быстро выполнить перенос данных это лучший вариант.


Комментариев нет:

Отправить комментарий