Почему не создаётся элемент справочника в приемнике при обмене в КД 2.1 и как это исправить?

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

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

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

Почему возникает «битая» ссылка (<Объект не найден>)?

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

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

Вместо полной выгрузки всех реквизитов справочника в XML-файл записывается только так называемая «легкая ссылка» (уникальный идентификатор GUID и поля поиска, такие как наименование или код). При этом системный параметр конвертации ТолькоПолучитьУзелСсылки автоматически принимает значение Истина.

Когда этот пакет данных загружается в базу-приемник, происходит следующее:

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

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

---

Решение 1. Использование параметра ТолькоПолучитьУзелСсылки в ПКО

Самый быстрый способ заставить систему принудительно выгружать объект целиком — это управление параметром ТолькоПолучитьУзелСсылки на уровне правил конвертации объектов (ПКО).

Для этого выполним следующие действия в конфигурации «Конвертация данных 2.1»:

  1. Найдем ПКО для нашего справочника (например, ПКО «Должности»).
  2. Перейдем на вкладку «Обработчики событий».
  3. Откроем обработчик события «Перед выгрузкой».
  4. Пропишем в нем простую строку кода:

ТолькоПолучитьУзелСсылки = Ложь;

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

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

---

Решение 2. Глобальное отключение оптимизации для всех справочников

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

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


// Если выгружаемый объект является справочником, принудительно выгружаем его целиком
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Источник)) Тогда
    ТолькоПолучитьУзелСсылки = Ложь;
КонецЕсли;

Если требуется применить это правило выборочно только к определенному списку справочников, код можно модифицировать:


// Массив типов, которые всегда должны выгружаться полностью
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Должности"));
МассивТипов.Добавить(Тип("СправочникСсылка.Подразделения"));

Если МассивТипов.Найти(ТипЗнч(Источник)) <> Неопределено Тогда
    ТолькоПолучитьУзелСсылки = Ложь;
КонецЕсли;

---

Решение 3. Точечная настройка через правила конвертации свойств (ПКС)

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

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

ВыгрузитьОбъект = Истина;

Установка переменной ВыгрузитьОбъект в значение Истина сообщает платформе, что объект, на который указывает данное свойство, должен быть выгружен в файл обмена полностью, независимо от глобальных настроек оптимизации плана обмена.

---

Решение 4. Принудительный программный вызов выгрузки

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

В обработчике ПКС «Перед выгрузкой» реквизита «Должность» пропишем следующий алгоритм:


// Отменяем стандартный механизм выгрузки свойства платформой
Отказ = Истина;

// Вызываем выгрузку программно
// Седьмой параметр функции отвечает за "ТолькоПолучитьУзелСсылки". 
// Передаем туда Ложь для полной выгрузки объекта.
ВыгрузитьПоПравилу(Источник.Должность, , , , "Должности", , Ложь);

---

Решение 5. Архитектурно правильный подход: Автоматическая регистрация изменений

Все предыдущие решения основывались на обходе оптимизации платформы внутри правил конвертации. Однако с точки зрения архитектуры 1С самым правильным подходом является своевременная регистрация связанных справочников на узле плана обмена.

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

Реализовать авторегистрацию можно с помощью подписки на события в конфигурации-источнике:

  1. Создадим подписку на событие ПриЗаписи для нужного документа.
  2. В модуле подписки напишем код, который при регистрации документа к обмену будет автоматически регистрировать и все его ключевые справочники:

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

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

---

Дополнительная проверка: Нюансы настройки поиска в ПКО

Если вы применили один из программных методов выгрузки объекта целиком, но в приемнике все равно отображается <Объект не найден>, обязательно проверьте настройки поиска в ПКО справочника:

Проанализировав все указанные методы, мы можем выбрать наиболее подходящий под конкретные требования производительности и архитектуры вашей системы.

← На главную