Как заполнить документ в приемнике на основании запроса к регистру в источнике через КД 2.1

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При настройке обмена данными между конфигурациями 1С часто возникает задача, когда в базе-источнике нет прямого объекта (документа или справочника), который нужно перенести, но есть данные в регистрах. В такой ситуации стандартная выгрузка «объект в объект» не подходит. Мы разберем, как правильно организовать выгрузку данных из регистра накопления и их преобразование в новые документы в базе-приемнике, используя возможности конфигурации «Конвертация данных 2.1».

Анализ типичных ошибок при реализации

Прежде чем перейти к правильному алгоритму, проанализируем ситуацию, описанную в теме. Часто разработчики пытаются пойти по пути «наименьшего сопротивления», который превращается в сложный и трудноотлаживаемый код. Рассмотрим схему: Запрос -> Таблица значений -> Сериализация в строку -> Параметр -> Десериализация в приемнике -> Цикл создания объектов.

Почему этот метод считается неэффективным (или, как выразились на форуме, «забиванием гвоздей микроскопом»):

  1. Избыточность кода: Вы вручную пишете то, что платформа умеет делать автоматически (создание объектов, заполнение реквизитов, запись, поиск дублей).
  2. Проблемы с производительностью: Перевод большой таблицы значений в строку (сериализация) потребляет огромное количество оперативной памяти. При больших объемах данных регистра это гарантированно приведет к ошибке Out of Memory.
  3. Нарушение логики КД: Конвертация данных предназначена для того, чтобы декларативно описывать правила, а не писать монолитные куски кода для ручного создания объектов в обработчиках.
  4. Многократное выполнение: Если поместить запрос в обработчик ПКО ПередВыгрузкой, он будет выполняться столько раз, сколько объектов выгружается, что мы и видим в сообщении автора темы (многократный вывод «ля ля ля»).

Правильный подход: Правила выгрузки данных (ПВД) с произвольным алгоритмом

Рассмотрим основной и самый надежный способ решения задачи. Вместо того чтобы пытаться втиснуть запрос в рамки существующего ПКО, мы создадим Правило выгрузки данных (ПВД), которое будет работать независимо от наличия объектов-источников в метаданных.

Разберем по шагам, как настроить такую выгрузку:

  1. Создаем новое ПВД в дереве правил.
  2. В поле «Способ выборки» устанавливаем значение Произвольный алгоритм.
  3. В поле «Правило конвертации» выбираем ПКО нашего документа-приемника.
  4. Основную логику пишем в обработчике Перед выгрузкой данных самого ПВД.

Проанализируем пример кода для обработчика Перед выгрузкой данных в ПВД:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Остатки.Склад КАК Склад,
    |   Остатки.Номенклатура КАК Номенклатура,
    |   Остатки.КоличествоОстаток КАК Количество
    |ИЗ
    |   РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаКонца, ) КАК Остатки";

Запрос.УстановитьПараметр("ДатаКонца", ДатаОкончания);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Создаем структуру для передачи данных в ПКО
    ДанныеДляВыгрузки = Новый Структура;
    ДанныеДляВыгрузки.Вставить("Дата", ТекущаяДата());
    ДанныеДляВыгрузки.Вставить("Склад", Выборка.Склад);
    ДанныеДляВыгрузки.Вставить("Номенклатура", Выборка.Номенклатура);
    ДанныеДляВыгрузки.Вставить("Количество", Выборка.Количество);
    
    // Вызываем стандартную функцию выгрузки по правилу
    ВыгрузитьПоПравилу(,, ДанныеДляВыгрузки,, "ИмяВашегоПКО");
КонецЦикла;

В данном примере функция ВыгрузитьПоПравилу является ключевой. Она берет нашу структуру ДанныеДляВыгрузки, сопоставляет её с правилом конвертации и формирует корректный XML-узел для приемника.

Настройка ПКО и использование «Входящих данных»

Теперь выясним, как настроить Правило конвертации объектов (ПКО), чтобы оно правильно принимало нашу структуру. Поскольку источника как такового нет (мы передаем структуру, а не объект БД), ПКО должно быть настроено особым образом.

Выполним следующие настройки в ПКО:

Разберем подробнее: когда мы передали структуру в третьем параметре функции ВыгрузитьПоПравилу, в ПКО эта структура становится доступной через переменную ВходящиеДанные. Если флаг «Получать из входящих данных» установлен, система автоматически ищет в этой структуре ключ, совпадающий с именем реквизита приемника, и подставляет значение.

Решение проблемы с зацикливанием и многократными сообщениями

Выясним причину ситуации, когда отладочные сообщения (например, Сообщить("ля ля ля")) выводятся слишком часто. Это происходит, если код запроса ошибочно помещен в обработчик ПКО ПередВыгрузкой или ПриВыгрузке.

Важно понимать иерархию вызовов в КД 2.1:

  1. ПВД (Перед выгрузкой данных): Выполняется один раз для всей группы данных. Это идеальное место для тяжелых запросов.
  2. ПКО (Перед выгрузкой): Выполняется для каждого конкретного объекта (или строки выборки). Если в запросе 1000 строк, и код запроса стоит здесь, вы получите 1000 выполнений запроса.
  3. ПКС (Перед выгрузкой): Выполняется для каждого реквизита каждого объекта.

Решение: Перенесите весь код инициализации запроса и обхода результата в ПВД. ПКО должно отвечать только за логику сопоставления полей, а не за выборку данных из базы.

Заполнение табличных частей

Часто данные из регистра нужно превратить не в один документ на каждую запись, а в один документ с множеством строк в табличной части. Посмотрим, как это реализовать.

В обработчике ПВД мы можем сгруппировать данные запроса так, чтобы передать в ВыгрузитьПоПравилу структуру, содержащую таблицу значений для ТЧ документа:


// В ПВД (Перед выгрузкой данных)
ДанныеДокумента = Новый Структура;
ДанныеДокумента.Вставить("Номер", "001");
ДанныеДокумента.Вставить("Дата", ТекущаяДата());

// Формируем таблицу для табличной части "Товары"
ТаблицаТоваров = Новый ТаблицаЗначений;
ТаблицаТоваров.Колонки.Добавить("Номенклатура");
ТаблицаТоваров.Колонки.Добавить("Количество");

// Заполняем таблицу из результата запроса...
// ...
ДанныеДокумента.Вставить("Товары", ТаблицаТоваров);

ВыгрузитьПоПравилу(,, ДанныеДокумента,, "ИмяПКО_Документа");

В ПКО документа для правила конвертации табличной части Товары в обработчике ПередВыгрузкой нужно будет прописать:

КоллекцияОбъектов = ВходящиеДанные.Товары;

Это укажет системе, что источником для строк табличной части является не объект базы данных, а переданная нами таблица значений.

Поиск и синхронизация при первоначальной загрузке

Поскольку мы работаем с данными регистра, у нас нет естественного уникального идентификатора (GUID) объекта-источника. Проанализируем, как избежать дублирования документов при повторных загрузках.

В ПКО документа обязательно настройте Поля поиска. Рассмотрим наиболее надежные варианты:

Если не настроить поля поиска, при каждой выгрузке 1С будет создавать новый экземпляр документа, что быстро приведет к замусориванию базы-приемника.

Заключение

Мы проанализировали наиболее эффективный способ конвертации данных из регистра в документы. Использование ПВД с произвольным алгоритмом и передача структуры через ВыгрузитьПоПравилу позволяет избежать медленной сериализации строк, лишних циклов в приемнике и обеспечивает прозрачную логику работы правил. Помните, что архитектурно правильное решение в «Конвертации данных» всегда минимизирует объем ручного кода в пользу стандартных механизмов платформы.

← На главную