Обычно программисты, при поступлении задачи на загрузку извне данных в базу данных 1С, начинают делать свои (продвинутые - начинают искать подходящие чужие) обработки загрузки данных, создавая новый велосипед для загрузки, пытаясь обработать им все видимые подводные камни и учесть все возможные косяки. Но мало кто задумывается, что в Конвертации все взаимосвязи, в т.ч. циклические, уже учтены. Нужно только грамотно положить в нее исходные данные и заставить работать УниверсальныйОбменДаннымиXML используя правила конвертации.
Итак начнем.
Цель: загрузить данные из внешнего источника (в нашем примере это будет результат запроса к БД MS SQL) в базу 1С (в нашем случае, это будет 1С:ERP). Загружать будем справочник Номенклатура.
Для этого заходим в программу Конвертация данных 2.1, загружаем структуру конфигурации 1С:ERP 2 и создаем новые правила обмена данными (из 1С:ERP в 1С:ERP).
Далее создаем ПКО (правила конвертации объектов) и ПВД (правила выгрузки данных) для конвертации и, соответственно, выгрузки справочника Номенклатура.
В ПВД указываем способ выборки "Произвольный алгоритм", правило конвертации "Номенклатура".
Код обработчика "Перед обработкой":
_д = "ДФ='yyyyMMdd HH:mm:ss'";
Результат = МодульИнтеграции.ВыполнитьЗапросНаСервере(
"select distinct dd.AID, dd.FullName from dDetails dd
|where dd.IdMeasures is not NULL
|"
,"Provider=SQLOLEDB;Data Source=SRVSQL;Initial Catalog=BASE;User ID=user1c;Password=12345;");
Если Результат <> Неопределено Тогда
ВыборкаДанных = Новый Массив;
Для каждого стрТЗ из Результат Цикл
_номенклатура = Новый Структура;
_номенклатура.Вставить("Код",стрТЗ.AID);
_номенклатура.Вставить("Наименование",стрТЗ.FullName);
_номенклатура.Вставить("ГруппаДоступа","Прочее");
ВыборкаДанных.Добавить(_номенклатура);
КонецЦикла;
КонецЕсли;
Тут я не буду расписывать модуль функции МодульИнтеграции.ВыполнитьЗапросНаСервере(). Предположим, что эта функция по указанному SQL запросу и параметрам подключения возвращает ТаблицуЗначений, соответствующую ожидаемому результату запроса.
На закладке Правила конвертации объектов создаем все необходимые для загрузки правила ПКО (ПКО - правила конвертации объектов) и соответствующие ПКС (ПКС - правила конвертации свойств). Для ПКО Номенклатура Код, Наименование и ГруппаДоступа забираем из передаваемых данных, остальные реквизиты заполняем синтетическими данными, которые описываем тут же, в ПКС.
Например структуру данных для конвертации реквизита ВидНоменклатуры заполняем в обработчике ПКС ПередВыгрузкой:
ТипНоменклатуры определяем так же в обработчике ПередВыгрузкой, значением перечисления:
Остальное аналогичным образом. (нюансы могу пояснить в комментариях, чтобы не засорять статью).
Мы получили XML-файл правил обмена.
Эти правила можно использовать типовой обработкой из БСП "УниверсальныйОбменДаннымиXML" (далее просто обработка) - выгрузить данные в XML, и этой же обработкой загрузить их в эту же базу уже из XML.
Но мы пойдем дальше.
Есть такое понятие как Online-обмен. Суть его в том, что обработка создает COM-экземпляр обработки в базе-получателе данных.
Данные в обработку-получатель передаются при записи обработкой-отправителем каждого узла XML в создаваемый файл данных (даже если это online-обмен, файл данных все же создается, пусть и неявно). Т.е. как только обработка-отправитель записывает очередной узел в файл с данными, этот же узел передается для загрузки обработке-получателю (не файл, а именно узел).
Но зачем же нам городить огород с COM-объектами?! Создадим еще один экземпляр объекта типовой обработки локально и укажем механизму конвертации использовать его так, как если бы это был COM-объект в случае online-обмена.
Собственно код, который делает эту замену:
// *** БЛОК ВКЛЮЧЕНИЯ ОНЛАЙН ОБМЕНА ***
// Для включения #online обмена при универсальной выгрузке
// Этот волшебный код обманывает универсальный механизм и переопределяет обработку, которая должна была быть создана COM-соединением.
// На самом деле мы ее создаем локально, просто другим объектом, чтобы уж совсем отторжения не было. Посмотрим, как оно взлетит...
мОбработкаДляЗагрузкиДанных = Обработки.УниверсальныйОбменДаннымиXML.Создать();
НепосредственноеЧтениеВИБПриемнике = Истина;
// заполняем необходимые свойства
ЗаполнитьЗначенияСвойств(мОбработкаДляЗагрузкиДанных,ЭтотОбъект,"ИспользоватьТранзакции,КоличествоОбъектовНаТранзакцию,ФлагРежимОтладки,ДописыватьДанныеВПротоколОбмена,ВыводВПротоколИнформационныхСообщений");
мОбработкаДляЗагрузкиДанных.РежимОбмена = "Загрузка";
мОбработкаДляЗагрузкиДанных.ИмяФайлаПротоколаОбмена = ПолучитьИмяПротоколаДляВторойИнформационнойБазыComСоединения();
ВыполнитьПередачуИнформацииОНачалеОбменаВПриемник(ТекущаяСтрокаДляЗаписи);
// *** КОНЕЦ БЛОКА ВКЛЮЧЕНИЯ ОНЛАЙН ОБМЕНА ***
Этот код нужно добавить в правила обмена в глобальный обработчик конвертации ПередВыгрузкойДанных (например так:). Пишу здесь, т.к. я этот обработчик добавляю программно при заполнении реквизитов Обработки.УниверсальныйОбменДаннымиXML, чтобы оставить возможность отладки.
Пример заполнения текста глобального обработчика ПередВыгрузкойДанных правил обмена при программном создании и запуске обработки обмена:
// Проконтролируем, что есть блок, включающий #online обмен
Если НЕ Найти(ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных,"мОбработкаДляЗагрузкиДанных") Тогда // можно конечно на хэш-тег ориентироваться, но оставил пока так
ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных = СокрЛП(ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных)
+Символы.ПС+ПолучитьМакет("Конвертация_БлокВключенияОнлайнОбмена").ПолучитьТекст();
КонецЕсли;
Собственно все.
Остается только ВыполнитьВыгрузку(), которая обработает включенные ПВД, загрузит данные из БД SQL, сформирует XML и сразу же выполнит его загрузку в эту же базу.
Ниже приведу код, которым я пользуюсь для программной загрузки данных с использованием правил конвертации:
ОбработкаОбмена = Обработки.УниверсальныйОбменДаннымиXML.Создать();
ИмяВременногоФайлаПравилОбмена = ПолучитьИмяВременногоФайла("xml");
ИмяВременногоФайлаПротоколаОбмена = ПолучитьИмяВременногоФайла("txt");
ИмяВременногоФайлаДанных = ПолучитьИмяВременногоФайла("xml");
МакетПравилОбмена.Записать(ИмяВременногоФайлаПравилОбмена);
ОбработкаОбмена.РежимОбмена = "Выгрузка";
ОбработкаОбмена.ИмяФайлаПравилОбмена = ИмяВременногоФайлаПравилОбмена;
ОбработкаОбмена.ВыводВПротоколИнформационныхСообщений = Истина;
ОбработкаОбмена.ВыводВПротоколСообщенийОбОшибках = Истина;
Если ЗначениеЗаполнено(ИмяВременногоФайлаПротоколаОбмена) Тогда
ОбработкаОбмена.ИмяФайлаПротоколаОбмена = ИмяВременногоФайлаПротоколаОбмена;
КонецЕсли;
ОбработкаОбмена.ЗагрузитьПравилаОбмена(ИмяВременногоФайлаПравилОбмена, "XMLФайл");
// Проконтролируем, что есть блок, включающий #online обмен
Если НЕ Найти(ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных,"мОбработкаДляЗагрузкиДанных") Тогда // можно конечно на хэш-тег ориентироваться, но оставил пока так
ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных = СокрЛП(ОбработкаОбмена.Конвертация.ПередВыгрузкойДанных)
+Символы.ПС+ПолучитьМакет("Конвертация_БлокВключенияОнлайнОбмена").ПолучитьТекст();
КонецЕсли;
// заполнение уточняющих параметров
Если ЗначениеЗаполнено(ПараметрыВыполнения) Тогда
ЗаполнитьЗначенияСвойств(ОбработкаОбмена.Параметры,ПараметрыВыполнения);
ЗаполнитьЗначенияСвойств(ОбработкаОбмена,ПараметрыВыполнения,"ДатаНачала,ДатаОкончания");
КонецЕсли;
ОбработкаОбмена.ИмяФайлаОбмена = ИмяВременногоФайлаДанных;
ОбработкаОбмена.ТаблицаНастройкиПараметров.Очистить();
// здесь мы включаем только конкретное ПВД, если их много, а нужно сделать выгрузку только по одному
_имяПВД = Неопределено;
Если ПараметрыВыполнения.Свойство("ИмяПВД",_имяПВД) Тогда
Для каждого стрТЗвыгрузки из ОбработкаОбмена.ТаблицаПравилВыгрузки.Строки.НайтиСтроки(Новый Структура("Включить",1),Истина) Цикл
стрТЗвыгрузки.Включить = 0;
КонецЦикла;
Для каждого стрТЗвыгрузки из ОбработкаОбмена.ТаблицаПравилВыгрузки.Строки.НайтиСтроки(Новый Структура("Имя",_имяПВД),Истина) Цикл
стрТЗвыгрузки.Включить = 1;
КонецЦикла;
КонецЕсли;
// Собственно сама выгрузка
ОбработкаОбмена.ВыполнитьВыгрузку();
// загрузка не нужна, т.к. механизм сам загрузит данные используя свой же online-обмен
P.S.
Итого имеем:
- универсальный механизм для загрузки любой информации из любого источника с использованием всем известного продукта (1С:Конвертация данных 2.1);
- правила загрузки понятны и легко модифицируемы - нет необходимости копаться в коде для понимания взаимосвязей загружаемых данных;
Есть планы по созданию БСП-совместимой универсальной обработки заполнения (фактически она создана, но пока не готова к публикации - в ней еще много наколенных методов) - идея в том, что все параметры обработки описываются в правилах обмена, команды = ПВД, параметры = JSON-комментарий, остальное в процессе. Останется только подсунуть в обработку правила обмена в виде макета и загрузить ее в базу (Дополнительные отчеты и обработки).
Всем спасибо за чтение, комментарии, плюсы!