Как в Конвертации данных 2.1 продублировать записи регистра сведений с заменой измерения

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

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

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

Выясним сначала, почему популярные решения с форумов часто оказываются не самыми оптимальными, а затем по шагам реализуем лучшее техническое решение.

---

Анализ подходов к решению задачи

В процессе обсуждения подобных задач на форумах разработчики обычно предлагают два основных варианта. Давайте проанализируем их эффективность и архитектурную чистоту.

Вариант 1. Переопределение значения в ПКС «При выгрузке»

Первая мысль, которая часто возникает у новичков — просто прописать подмену значения непосредственно в правиле конвертации свойства (ПКС) для измерения Подразделение, используя конструкцию:

Значение = Параметры.НовоеПодразделение;

Выясним причину, почему этот способ не решит задачу удвоения данных. Если мы просто переопределим значение свойства «При выгрузке», система выполнит обычную замену. В файл выгрузки уйдет только одна измененная запись, а исходная запись с первоначальным подразделением будет утеряна. Дублирования (копирования) данных в приемнике не произойдет.

Вариант 2. Использование двух разных ПКО и вызов ВыгрузитьПоПравилу (Метод с форума)

Для того чтобы обойти ограничение первого варианта, участники форума предложили рабочую схему:

  1. Создать два абсолютно одинаковых правила конвертации объектов (ПКО) для одного и того же регистра сведений.
  2. В первом ПКО выгружать данные «как есть».
  3. Во втором ПКО в правиле конвертации свойства (ПКС) для измерения Подразделение принудительно подменять значение на новое через Значение = ....
  4. В правиле выгрузки данных (ПВД) вызвать процедуру ВыгрузитьПоПравилу дважды — сначала для первого ПКО, затем для второго.

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

Посмотрим, как решить эту задачу изящно и профессионально с использованием всего одного ПКО.

---

Оптимальное решение: Одно ПКО + Произвольный алгоритм в ПВД

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

Разберем по шагам, как настроить правила конвертации для реализации этого алгоритма.

Шаг 1. Настройка Правила конвертации объектов (ПКО)

Нам потребуется создать одно гибкое ПКО, которое будет получать данные не напрямую из объектной выборки источника, а из переданной структуры.

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

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

Шаг 2. Настройка Параметров конвертации

Чтобы не зашивать конкретные ссылки на подразделения жестко в программный код (что считается крайне плохим тоном в разработке), создадим глобальные параметры конвертации.

  1. В КД перейдите в настройки конвертации на вкладку «Параметры».
  2. Создайте параметр ПодразделениеИсточник (тип значения — ссылка на справочник подразделений в источнике).
  3. Создайте параметр ПодразделениеПриемник (тип значения — ссылка на справочник подразделений в приемнике).
  4. Для обоих параметров установите флаг «Диалог». Это позволит пользователю интерактивно выбирать конкретные подразделения непосредственно перед запуском выгрузки в обработке «Универсальный обмен данными в формате XML» .

Шаг 3. Настройка Правила выгрузки данных (ПВД)

Теперь настроим правило выгрузки данных, которое будет отвечать за выборку информации из базы-источника и запуск механизма дублирования.

  1. Создайте новое ПВД для нашего регистра сведений.
  2. Укажите способ выборки данных: «Произвольный алгоритм».
  3. Откройте обработчик событий «Перед выгрузкой» для этого ПВД и напишите код, представленный ниже.

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


// 1. Отменяем стандартную автоматическую выгрузку объектов
Отказ = Истина; 

// 2. Формируем запрос для выборки нужных записей из базы-источника
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Рег.Период КАК Период,
    |   Рег.Номенклатура КАК Номенклатура,
    |   Рег.Подразделение КАК Подразделение,
    |   Рег.Цена КАК Цена
    |ИЗ
    |   РегистрСведений.ЦеныНоменклатуры КАК Рег
    |ГДЕ
    |   Рег.Подразделение = &ИсходноеПодразделение";

// Устанавливаем параметр запроса на основе выбранного пользователем значения на форме выгрузки
Запрос.УстановитьПараметр("ИсходноеПодразделение", Параметры.ПодразделениеИсточник); 

Выборка = Запрос.Выполнить().Выбрать();

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

КонецЦикла;

Рассмотрим подробнее логику работы этого скрипта. Мы принудительно устанавливаем Отказ = Истина, чтобы платформа 1С не пыталась выполнить стандартную выгрузку по умолчанию. Затем мы программно обходим выборку запроса. На каждой итерации цикла мы создаем две независимые структуры ВходящиеДанные. В первой структуре мы оставляем оригинальное подразделение, во второй — подставляем новое подразделение из параметров обмена. Функция ВыгрузитьПоПравилу вызывается дважды, транслируя обе структуры в XML-файл выгрузки.

---

Важные технические нюансы при переносе регистров сведений

При работе с регистрами сведений в среде 1С через механизмы конвертации данных крайне важно учитывать специфику их записи в информационную базу. Рассмотрим ключевые особенности:

  1. Уникальность и замещение записей при загрузке:

    В отличие от справочников или документов, элементы которых идентифицируются уникальным идентификатором (UUID), записи регистров сведений идентифицируются исключительно набором значений их ключевых полей — то есть измерений (и дополнительно полем Период, если регистр является периодическим). Поскольку в нашем алгоритме мы подменяем измерение Подразделение, для платформы 1С оригинальная запись и копия будут являться абсолютно разными ключевыми записями. В базе-приемнике они успешно запишутся как две независимые строки, не конфликтуя и не затирая друг друга.

    Обратите внимание: Если бы вы дублировали записи, меняя только ресурс (например, Цена) при одинаковых измерениях, то при загрузке вторая запись просто перезаписала бы первую.

  2. Периодичность регистра:

    Если переносимый регистр сведений является периодическим, обязательно включайте поле Период во входящие данные и передавайте его значение. Если этого не сделать, при загрузке период может установиться в дефолтную дату «01.01.0001», либо система выдаст ошибку транзакции при попытке записи набора.

  3. Режим записи наборов (Очистка перед загрузкой):

    По умолчанию Конвертация данных производит загрузку независимых регистров сведений наборами записей. Если вам требуется, чтобы перед загрузкой новых данных старые записи по целевому подразделению в базе-приемнике очищались, вам необходимо дополнительно настроить обработчик ПКО ПередЗаписьюНабораЗаписей на стороне приемника или корректно настроить правила очистки данных при загрузке.

Резюме

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

← На главную