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