Как настроить перенос значения из составного типа ПВХ в справочник-приемник в «1С:Конвертация данных 2.1» и избежать ошибок сопоставления

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

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

В этой статье мы подробно разберем, почему при стандартном сопоставлении свойств возникает популярная ошибка «битых» ссылок (символы <> в базе-приемнике), как правильно переопределить логику выгрузки в обработчиках ПКС (Правила конвертации свойств) и как оптимизировать этот процесс для исключения проблем с производительностью СУБД.

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

---

Анатомия проблемы: исходные данные и суть конфликта типов

Давайте подробно проанализируем структуру данных, с которой предстоит работать:

  1. Источник: Документ Заявка на оплату. В его табличной части ДвиженияОперации присутствует реквизит Аналитика1 с типом данных ПланВидовХарактеристикСсылка. Одно из допустимых значений этого ПВХ — элемент справочника КодификаторСтатейЛимитов. Внутри этого справочника есть реквизит КОСГУ (тип ссылки — СправочникСсылка.КОСГУ).
  2. Приемник: Документ Заявка на кассовый расход. В его табличной части РасшифровкаПлатежа есть реквизит КОСГУНазначениеПлатежа, который имеет строгий тип СправочникСсылка.КОСГУ.

Попытка решения «в лоб»: разработчик сопоставил ПКС для табличной части, указав в качестве источника Аналитика1, а приемника — КОСГУНазначениеПлатежа. В обработчике события При выгрузке ПКС был написан следующий код:


Если ТипЗнч(ОбъектКоллекции.Аналитика1) = Тип("СправочникСсылка.КодификаторСтатейЛимитов") Тогда
    ИмяПКО = "КОСГУ";
Иначе 
    Отказ = Истина;
КонецЕсли;

Результат: после выполнения обмена в документе-приемнике вместо заполненного кода КОСГУ отображалась пустая («битая») ссылка в виде знаков <>.

---

Выясняем причину: почему возникает «битая» ссылка (<>)?

Выгрузка в КД 2.1 работает по строгому алгоритму. Когда мы указываем для свойства КОСГУНазначениеПлатежа источник Аналитика1 и принудительно назначаем правило конвертации ИмяПКО = "КОСГУ", платформа пытается обработать переданный ей объект. Но в ОбъектКоллекции.Аналитика1 на этот момент хранится ссылка на справочник КодификаторСтатейЛимитов, а не на КОСГУ!

Правило конвертации объектов (ПКО) КОСГУ настроено на чтение свойств из источника типа СправочникСсылка.КОСГУ (например, реквизитов Код и Наименование). Получив вместо этого объект КодификаторСтатейЛимитов, механизм конвертации пытается прочитать у него эти свойства. Так как структура данных не совпадает (или не совпадают уникальные идентификаторы GUID), в XML-файл выгрузки записывается некорректная информация о полях поиска.

При загрузке в базе-приемнике платформа пытается найти элемент справочника КОСГУ по дефектным ключевым полям или неверному GUID. Поиск завершается неудачей. В базу записывается пустая ссылка без представления, что в интерфейсе «1С:Предприятия» выглядит как пустая строка или значки <>.

---

Вариант решения №1: Динамическое переопределение значения в ПКС (Простой способ)

Для того чтобы система корректно отработала выгрузку по правилу КОСГУ, нам нужно передать в механизм конвертации не сам элемент ПВХ (справочник-владелец), а непосредственно значение его реквизита — ссылку на справочник КОСГУ.

Давайте разберем по шагам, как настроить ПКС в интерфейсе конфигурации «Конвертация данных»:

  1. Откройте правила конвертации свойств (ПКС) для табличной части документа.
  2. Найдите строку свойства КОСГУНазначениеПлатежа.
  3. Очистите поле «Источник». Это ключевой шаг: мы сообщаем системе, что значение свойства не будет извлекаться автоматически из одноименного реквизита источника, а будет рассчитано программно.
  4. В поле «Приемник» должно быть указано КОСГУНазначениеПлатежа.
  5. Укажите соответствующее «Правило конвертации» (ПКО) — КОСГУ.
  6. Откройте обработчик события Перед выгрузкой (или При выгрузке) данного ПКС и напишите следующий код:

Если ТипЗнч(ОбъектКоллекции.Аналитика1) = Тип("СправочникСсылка.КодификаторСтатейЛимитов") Тогда
    // Явно получаем вложенный реквизит КОСГУ и передаем его в предопределенную переменную Значение
    Значение = ОбъектКоллекции.Аналитика1.КОСГУ;
Иначе 
    // Если тип аналитики другой, отменяем выгрузку этого свойства для текущей строки ТЧ
    Отказ = Истина;
КонецЕсли;

Как это работает: теперь в переменную Значение попадает чистая ссылка на справочник КОСГУ. Механизм КД берет эту ссылку, обращается к ПКО КОСГУ, находит нужные поля поиска (код, наименование) и корректно формирует XML-пакет. Приемник без труда находит элемент в своей базе.

---

Вариант решения №2: Оптимизация производительности (Профессиональный подход)

Хотя решение из Варианта №1 полностью рабочее, оно таит в себе скрытую угрозу для производительности системы. Обращение через точку к реквизитам связанных объектов (ОбъектКоллекции.Аналитика1.КОСГУ) внутри цикла обхода табличной части приводит к возникновению проблемы N+1 запросов.

Если в выгружаемом документе содержится 100 строк, платформа сделает 100 отдельных, одиночных запросов к базе данных для получения реквизита КОСГУ для каждой строки. При выгрузке тысяч документов процесс обмена может затянуться на часы. Рассмотрим два способа оптимизации выгрузки.

Способ А. Кэширование с помощью функций БСП

Если ваша конфигурация-источник построена на базе Библиотеки стандартных подсистем (БСП), мы можем использовать оптимизированные методы чтения реквизитов. Функция ОбщегоНазначения.ЗначениеРеквизитаОбъекта использует внутренние механизмы кэширования платформы, что существенно снижает нагрузку на СУБД:


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

Способ Б. Выгрузка данных через запрос и «ИсходящиеДанные» (Наиболее эффективный)

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

Разберем, как это реализовать:

  1. В ПКО документа-источника найдите обработчик события Перед выгрузкой.
  2. Напишите запрос, который левым соединением или явным приведением типов (ВЫРАЗИТЬ) сразу получает значение КОСГУ из аналитики:

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

Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

// Записываем полученную таблицу в структуру ИсходящиеДанные
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("РасшифровкаПлатежа", РезультатЗапроса);
  1. Перейдите в ПКО документа, найдите Правило конвертации группы свойств (ПКГС) для табличной части РасшифровкаПлатежа.
  2. В настройках ПКГС установите флаг «Получить из входящих данных».
  3. В подчиненных ПКС (например, для КОСГУНазначениеПлатежа) укажите источником соответствующую колонку таблицы (в нашем случае — КОСГУНазначениеПлатежа).

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

---

Повышение отказоустойчивости кода

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

Посмотрим на пример безопасного написания кода в ПКС:


Значение = Неопределено;
ТекущаяАналитика = ОбъектКоллекции.Аналитика1;

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

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

← На главную