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