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