Как правильно применить функцию ВыгрузитьРегистр() для переноса контактной информации между базами 1С?

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

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

Разбор проблемы: почему возникает ошибка «Поле объекта не обнаружено (Активность)»

Часто программисты пытаются сформировать данные для регистра вручную, используя Таблицу Значений или Структуру, и передать её в функцию ВыгрузитьРегистр(). Проанализируем типичный неудачный пример кода, который часто встречается на практике:


// Фрагмент кода, вызывающий ошибку
Отбор = Новый ТаблицаЗначений;
Отбор.Колонки.Добавить("Имя");
Отбор.Колонки.Добавить("Значение");
СтрокаОтбора = Отбор.Добавить();
СтрокаОтбора.Имя = "Объект";
СтрокаОтбора.Значение = Источник.Ссылка;

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

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

Решение №1: Использование объекта НаборЗаписей (рекомендуемый способ)

Чтобы избежать проблем с отсутствующими системными полями, наиболее надежным способом является использование штатного объекта платформы — РегистрСведенийНаборЗаписей. Рассмотрим исправленный код, который следует разместить в обработчике «После выгрузки» ПКО Контрагенты:


// Создаем запрос для получения ключей записей КИ текущего объекта
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    КИ.Тип,
               |    КИ.Вид
               |ИЗ
               |    РегистрСведений.КонтактнаяИнформация КАК КИ
               |ГДЕ
               |    КИ.Объект = &Объект";
Запрос.УстановитьПараметр("Объект", Источник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();

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

В данном примере мы используем метод Набор.Прочитать(). Это ключевой момент: платформа сама заполняет структуру набора всеми необходимыми полями, включая те, о которых мы могли забыть или не знать. Функция ВыгрузитьРегистр() получает «родной» объект 1С и корректно упаковывает его в XML.

Решение №2: Оптимизация выгрузки (без цикла по каждой записи)

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


Набор = РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей();
// Устанавливаем фильтр только по владельцу (Объекту)
Набор.Отбор.Объект.Установить(Источник.Ссылка);
Набор.Прочитать();

Если Набор.Количество() > 0 Тогда
    // Выгружаем весь набор целиком за один вызов
    ВыгрузитьРегистр(Набор, , , , "КонтактнаяИнформация");
КонецЕсли;

Этот метод значительно быстрее. Однако будьте осторожны: если в правилах конвертации (ПКО) для регистра сведений настроены сложные поля поиска (например, по Типу и Виду), выгрузка всего набора сразу может привести к тому, что на стороне приемника старые записи будут замещены новыми полностью. Если это именно то, что вам нужно (синхронизация КИ «один в один»), используйте этот вариант.

Решение №3: Выгрузка через ПКС и функцию ВыгрузитьПоПравилу()

Существует еще один архитектурно более правильный подход в рамках методологии «Конвертации данных». Вместо написания кода в ПослеВыгрузки, мы можем создать виртуальное свойство. Посмотрим, как это реализовать:

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

// Формируем запрос для получения данных КИ
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ РегистрСведений.КонтактнаяИнформация ГДЕ Объект = &Объект");
Запрос.УстановитьПараметр("Объект", Источник.Ссылка);
ТаблицаКИ = Запрос.Выполнить().Выгрузить();

// Если данные есть, передаем их в переменную Значение
// КД сама вызовет ПКО для регистра для каждой строки этой таблицы
Значение = ТаблицаКИ;

В этом случае в ПКО регистра в обработчике ПередВыгрузкой нужно будет убедиться, что входящие данные (строка таблицы) корректно сопоставляются с полями регистра. Преимущество этого метода в том, что выгрузка КИ становится частью структуры объекта-владельца в XML-файле, что более наглядно при отладке.

Важные нюансы при обмене КИ

При работе с контактной информацией важно учитывать несколько технических деталей:

Таким образом, мы выяснили, что наиболее стабильным способом переноса КИ является программное создание НабораЗаписей с обязательным вызовом метода Прочитать() перед выгрузкой. Это гарантирует корректную структуру данных и отсутствие ошибок при выполнении правил обмена.

← На главную