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