Как в Конвертации данных 2.1 создать несколько объектов в приемнике на основании одного запроса из источника?

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

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

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

Способ 1. Использование ВыгрузитьПоПравилу() и структуры ВходящиеДанные

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

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

Для реализации логики нам потребуется создать новое ПВД. Обратите внимание на следующие настройки:

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

Шаг 2. Написание программного кода в обработчике «Перед обработкой»

Рассмотрим пример кода. Сначала мы выполняем запрос к источнику, затем обходим его результат в цикле, формируем структуру ВходящиеДанные и вызываем функцию ВыгрузитьПоПравилу(). В самом конце обязательно отменяем стандартную обработку выгрузки.


// 1. Формируем и выполняем запрос к источнику данных
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КонтактныеЛица.Наименование КАК ФИО,
    |	КонтактныеЛица.ДатаРождения КАК ДатаРождения,
    |	КонтактныеЛица.Телефон КАК Телефон,
    |	КонтактныеЛица.ЭлектроннаяПочта КАК Почта
    |ИЗ
    |	Справочник.КонтактныеЛица КАК КонтактныеЛица
    |ГДЕ
    |	НЕ КонтактныеЛица.ПометкаУдаления";

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

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

// 3. Отменяем стандартную обработку ПВД, так как мы полностью обработали данные вручную
Отказ = Истина;

Важное примечание: Если в конце обработчика не написать Отказ = Истина;, система попытается выполнить стандартную выгрузку для данного ПВД, что приведет к ошибкам выполнения, так как объект выборки не задан.

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

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

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

Важный нюанс: Борьба с кэшированием объектов

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

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

Для решения этой проблемы существует два надежных метода:

Решение А: Настройка ПКО (Рекомендуется)
В настройках ПКО на вкладке «Настройки» установите флаг «Не запоминать выгруженные объекты». Это отключит кэширование для данного правила, и КД будет генерировать новый XML-узел при каждом вызове функции выгрузки.

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


КлючВыгружаемыхДанных = ВходящиеДанные.Наименование + "_" + Строка(ВходящиеДанные.ДатаРождения);

Благодаря этому КД поймет, что перед ней разные сущности, и выгрузит каждую запись выборки.

Способ 2. Использование предопределенной таблицы «ВыборкаДанных»

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

При таком подходе мы передаем платформе готовую таблицу значений с данными, а КД сама автоматически обходит её строки и сопоставляет их с правилами конвертации.

Алгоритм настройки:

1. В настройках ПВД укажите способ выборки «Произвольный алгоритм» и выберите нужное ПКО.

2. В обработчике ПВД Перед обработкой напишите следующий код:


// Создаем таблицу значений с колонками, имена которых совпадают с ПКС или реквизитами источника
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Наименование");
ТаблицаДанных.Колонки.Добавить("ДатаРождения");
ТаблицаДанных.Колонки.Добавить("Телефон");
ТаблицаДанных.Колонки.Добавить("Email");

// Выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КонтактныеЛица.Наименование КАК Наименование,
    |	КонтактныеЛица.ДатаРождения КАК ДатаРождения,
    |	КонтактныеЛица.Телефон КАК Телефон,
    |	КонтактныеЛица.ЭлектроннаяПочта КАК Email
    |ИЗ
    |	Справочник.КонтактныеЛица КАК КонтактныеЛица";

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

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

// Помещаем таблицу в предопределенную переменную КД
ВыборкаДанных = ТаблицаДанных;

Преимущества этого способа:

Предотвращение дублирования объектов в базе-приемнике

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

Если запустить такой обмен повторно, система при загрузке не сможет сопоставить объекты по UID и создаст дубликаты. Чтобы этого не произошло, необходимо правильно настроить поля поиска в ПКО:

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

При такой настройке перед созданием нового контрагента система сначала выполнит запрос к базе-приемнику, попытается найти уже существующего контрагента с аналогичными ФИО и датой рождения, и произведет обновление данных вместо создания дубликата.

← На главную