Часто перед разработчиками встает задача автоматизировать передачу данных между различными базами 1С, например, организовать одностороннюю выгрузку из 1С:ERP в 1С:Бухгалтерию предприятия. Для этого удобно использовать правила конвертации данных и типовую обработку УниверсальныйОбменДаннымиXML. Разберем по шагам, как правильно написать код для регламентного задания, чтобы обмен работал автоматически, учитывал регистрацию изменений на узлах плана обмена и не вызывал ошибок при фоновом выполнении.
Для начала создадим процедуру, которая будет вызываться регламентным заданием. Проанализируем базовый код инициализации. Нам нужно программно создать экземпляр обработки, указать режим обмена, период выгрузки и пути к файлам.
Процедура ВыгрузкаИзЕрп() Экспорт
Обработка = Обработки.УниверсальныйОбменДаннымиXML.Создать();
Обработка.РежимОбмена = "Выгрузка";
Обработка.ДатаНачала = НачалоДня(ДобавитьМесяц(ТекущаяДата(), -1));
Обработка.ДатаОкончания = КонецМесяца(ТекущаяДата());
// Внимание! Пути должны быть доступны серверу 1С
Обработка.ИмяФайлаОбмена = "\\ServerName\Exchange\ЕРП-БУХ_Данные.xml";
Обработка.ИмяФайлаПравилОбмена = "\\ServerName\Exchange\ЕРП-БУХ_Правила.xml";
КонецПроцедуры
Важно: рассмотрим особенности выполнения кода в регламентном задании. Так как код выполняется на сервере от имени системного пользователя (например, USR1CV8), использование локальных дисков (например, D:\Exchange\...) часто приводит к ошибкам из-за нехватки прав доступа. Рекомендуется использовать общие сетевые папки (UNC-пути).
Кроме того, при фоновом выполнении отсутствует пользовательский интерфейс. Если обработка попытается вывести сообщение пользователю, задание завершится с ошибкой. Поэтому обязательно отключим вывод сообщений:
Обработка.ВыводВОкноСообщенийИнформационныхСообщений = Ложь;
Разберем процесс чтения правил. Если вы изучали работу обработки в пользовательском режиме, то могли заметить асинхронные вызовы вроде ПрочитатьПравилаОбменаЗавершение. В серверном коде для регламентного задания они не нужны. Посмотрим на простой и эффективный метод:
Обработка.ЗагрузитьПравилаОбмена();
Этот метод работает синхронно. Сразу после его выполнения внутреннее дерево правил Обработка.ТаблицаПравилВыгрузки будет заполнено и готово к дальнейшей работе.
Выясним причину частой ошибки начинающих разработчиков: попытка передать в качестве узла обмена простую строку или несуществующую переменную (например, ПланОбменаЕРП). Платформа выдаст ошибку "Переменная не определена". В обработку необходимо передать конкретную ссылку на элемент базы данных (узел плана обмена). Получим эту ссылку с помощью поиска по коду:
УзелДляВыгрузки = ПланыОбмена.ИмяВашегоПланаОбмена.НайтиПоКоду("КодУзлаПриемника");
Теперь рассмотрим, как привязать этот узел к правилам выгрузки, чтобы обработка понимала, по какому узлу нужно читать зарегистрированные изменения. Для этого потребуется рекурсивная процедура, которая обойдет дерево правил и установит узел для каждой строки:
&НаСервере
Процедура УстановитьУзелОбменаУСтрокДерева(Дерево, УзелОбмена) Экспорт
Для Каждого Строка Из Дерево Цикл
Если Строка.ЭтоГруппа Тогда
УстановитьУзелОбменаУСтрокДерева(Строка.ПолучитьЭлементы(), УзелОбмена);
Иначе
Строка.СсылкаНаУзелОбмена = УзелОбмена;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Вызовем эту процедуру, передав в нее заполненное дерево правил:
УстановитьУзелОбменаУСтрокДерева(Обработка.ТаблицаПравилВыгрузки.ПолучитьЭлементы(), УзелДляВыгрузки);
Проанализируем ситуацию с удалением регистрации. Если мы просто выгрузим данные, они останутся "висеть" на узле, и при следующем сеансе обмена файл станет еще больше. Свойство ТипУдаленияРегистрацииИзмененийДляУзловОбменаПослеВыгрузки управляет этим поведением:
Установим значение 1, чтобы оптимизировать обмен.
Соберем все шаги воедино и посмотрим на итоговый рабочий код общего модуля, который можно смело подключать к регламентному заданию:
Процедура ВыгрузкаИзЕрп() Экспорт
Обработка = Обработки.УниверсальныйОбменДаннымиXML.Создать();
Обработка.РежимОбмена = "Выгрузка";
Обработка.ДатаНачала = НачалоДня(ДобавитьМесяц(ТекущаяДата(), -1));
Обработка.ДатаОкончания = КонецМесяца(ТекущаяДата());
// Настройки путей (используем UNC)
Обработка.ИмяФайлаОбмена = "\\ServerName\Exchange\ЕРП-БУХ_Данные.xml";
Обработка.ИмяФайлаПравилОбмена = "\\ServerName\Exchange\ЕРП-БУХ_Правила.xml";
// Запрет вывода сообщений для фонового задания
Обработка.ВыводВОкноСообщенийИнформационныхСообщений = Ложь;
// Синхронная загрузка правил
Обработка.ЗагрузитьПравилаОбмена();
// Получение узла обмена по коду
УзелДляВыгрузки = ПланыОбмена.ОбменУПП_БУХ.НайтиПоКоду("БП");
// Установка узла обмена в дерево правил
УстановитьУзелОбменаУСтрокДерева(Обработка.ТаблицаПравилВыгрузки.ПолучитьЭлементы(), УзелДляВыгрузки);
// Очистка регистрации после выгрузки
Обработка.ТипУдаленияРегистрацииИзмененийДляУзловОбменаПослеВыгрузки = 1;
// Запуск выгрузки
Обработка.ВыполнитьВыгрузку();
КонецПроцедуры
// Рекурсивный обход дерева правил
Процедура УстановитьУзелОбменаУСтрокДерева(Дерево, УзелОбмена) Экспорт
Для Каждого Строка Из Дерево Цикл
Если Строка.ЭтоГруппа Тогда
УстановитьУзелОбменаУСтрокДерева(Строка.ПолучитьЭлементы(), УзелОбмена);
Иначе
Строка.СсылкаНаУзелОбмена = УзелОбмена;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Используя данный подход, вы сможете организовать стабильную автоматическую выгрузку данных, корректно управляя регистрацией изменений в распределенных базах 1С.