При настройке обмена данными в среде 1С:Конвертация данных 2.0 (КД2) часто возникают ситуации, когда стандартной выгрузки объектов «по ссылкам» недостаточно. Одной из классических задач является необходимость выгрузить родительский объект (например, Документ1) и строго ограниченный набор подчиненных ему объектов (например, Справочник1), которые связаны через реквизит. При этом мы хотим избежать выгрузки лишних элементов справочника, не относящихся к выгружаемым документам. Рассмотрим детально, как решить эту задачу, используя программные возможности КД2.
Наиболее прямолинейный способ, который помог автору темы, — это вызов функции ВыгрузитьПоПравилу непосредственно из обработчика документа. Разберем этот алгоритм по шагам.
Допустим, у нас есть Правило Выгрузки Данных (ПВД) для объекта Документ1. Наша задача — в момент выгрузки документа найти все элементы Справочник1, ссылающиеся на этот документ, и принудительно их выгрузить.
Для этого в ПВД Документ1 в обработчике «После выгрузки» мы пропишем следующий код:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Справочник1.Ссылка КАК Ссылка
|ИЗ
| Справочник.Справочник1 КАК Справочник1
|ГДЕ
| Справочник1.СсылкаНаДокумент1 = &ТекущийДокумент";
Запрос.УстановитьПараметр("ТекущийДокумент", Объект);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Выгружаем найденный элемент справочника по конкретному правилу ПКО
ВыгрузитьПоПравилу(Выборка.Ссылка, , , , "Справочник1");
КонецЦикла;
Важный нюанс: при таком подходе в ПКО (Правила Конвертации Объектов) для справочника желательно отключить стандартное ПВД, чтобы система не пыталась выгрузить все элементы справочника скопом, а работала только по нашему программному вызову.
Иногда просто выгрузить объект недостаточно — нужно передать из документа в справочник какую-то контекстную информацию, которой нет в самом справочнике. В этом нам поможет структура ИсходящиеДанные. Рассмотрим ситуацию, когда при создании справочника в базе-приемнике нам нужно заполнить реквизит данными из шапки выгруженного документа.
Проанализируем шаги настройки:
// В обработчике ПВД Документа
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("ДополнительноеОписание", Объект.Комментарий);
// Передаем структуру в четвертый параметр функции
ВыгрузитьПоПравилу(СсылкаНаСправочник, , , СтруктураПараметров, "Справочник1");
Если ВходящиеДанные <> Неопределено Тогда
Значение = ВходящиеДанные.ДополнительноеОписание;
Иначе
// Если справочник выгружается сам по себе, можно задать логику по умолчанию
Отказ = Истина;
КонецЕсли;
Это позволяет гибко управлять заполнением реквизитов объекта-приемника на основе данных объекта-источника, даже если они напрямую не связаны иерархией реквизитов.
Если документов много, итерационный вызов ВыгрузитьПоПравилу внутри цикла может существенно замедлить процесс выгрузки. Разберем более производительный вариант — использование ПВД с типом выборки «Произвольный запрос» для Справочник1.
Вместо того чтобы «толкать» выгрузку справочника из документа, мы настроим ПВД справочника так, чтобы оно само выбирало только нужные записи. Текст запроса в ПВД будет выглядеть так:
ВЫБРАТЬ
Справочник1.Ссылка
ИЗ
Справочник.Справочник1 КАК Справочник1
ГДЕ
Справочник1.СсылкаНаДокумент1 В (ВЫБРАТЬ Документ1.Ссылка ИЗ Документ.Документ1 КАК Документ1 ГДЕ <ВашиУсловияНаДокументы>)
Такой подход позволяет СУБД выполнить оптимизированную выборку. Мы гарантируем, что в файл обмена попадут только те элементы Справочник1, для которых существуют соответствующие записи в таблице Документ1.
В сложных обменах бывает необходимо передать список «разрешенных» к выгрузке объектов через всю сессию выгрузки. Для этого используем глобальный параметр Параметры.
Выясним, как это реализовать:
Параметры.Вставить("СписокВыгруженныхДокументов", Новый Массив);
Параметры.СписокВыгруженныхДокументов.Добавить(Источник.Ссылка);
// Обработчик ПВД Справочника ПередВыгрузкой
Если Параметры.СписокВыгруженныхДокументов.Найти(Объект.СсылкаНаДокумент1) = Неопределено Тогда
Отказ = Истина;
КонецЕсли;
Этот метод удобен тем, что он разделяет логику выгрузки разных объектов, сохраняя при этом общую связность данных через глобальный контекст.
Бывают случаи, когда в базу-приемник нужно передать не просто значение реквизита, а некую инструкцию для алгоритма загрузки. Например, нужно ли обновлять существующий справочник или только создавать новые записи.
Рассмотрим использование функции УстановитьАтрибут. При программной выгрузке через ВыгрузитьПоПравилу создается XML-узел. Мы можем модифицировать его структуру:
// В ПВД или ПКО при выгрузке
УзелОбъекта = СформироватьУзелОбъекта(...); // Внутренние механизмы КД
УстановитьАтрибут(УзелОбъекта, "РежимЗагрузки", "ТолькоОбновление");
На стороне загрузки, в обработчике «Перед загрузкой», мы проанализируем этот атрибут:
// ПКО Справочника на стороне приемника
Режим = Пакет.ПолучитьАтрибут("РежимЗагрузки");
Если Режим = "ТолькоОбновление" И ОбъектМодифицирован Тогда
// Ваша логика
КонецЕсли;
Посмотрим на общую картину: при работе с КД2 важно помнить, что сначала отрабатывают ПВД (Правила выгрузки данных), а затем объекты могут выгружаться «по ссылкам» в процессе работы ПКО. Если вы используете ВыгрузитьПоПравилу внутри документа, связанный справочник попадет в тот же XML-контейнер, что и документ. Это критично для транзакционной целостности: если загрузка документа прервется ошибкой, связанные с ним программно выгруженные объекты также могут не попасть в базу-приемник, что предотвратит появление «мусорных» данных.
Используя предложенные методы, мы можем реализовать обмен любой сложности, сохраняя контроль над каждым передаваемым байтом данных.