Как в 1С:Конвертации данных передать значения новых реквизитов без обновления структуры конфигурации в правилах обмена

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

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

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

Почему не работает стандартная передача через ВходящиеДанные?

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

Выясним причину: коллекция ВходящиеДанные в КД 2.1 предназначена исключительно для локальной передачи параметров между различными правилами на этапе выгрузки (в источнике). Эти данные не сериализуются в XML-файл автоматически и не доходят до базы-приемника. Чтобы данные дошли до приемника, они должны быть явно записаны в XML-структуру файла обмена.

Решение: Использование виртуального ПКС и передача в параметры

Для реализации этой задачи нам не потребуется обновлять метаданные в КД. Мы настроим передачу информации через «виртуальное» ПКС (Правило конвертации свойства) и механизм параметров объекта. Разберем этот процесс по шагам.

Шаг 1. Создание виртуального ПКС в правиле конвертации объекта (ПКО)

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

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

Шаг 2. Написание кода на стороне выгрузки (в источнике)

Теперь нам нужно передать значение из источника в созданный параметр. Откроем обработчик события «Перед выгрузкой» для созданного нами ПКС.

Проанализируем ситуацию: в некоторых базах-источниках этого реквизита также может не быть. Чтобы избежать ошибок выполнения кода, напишем безопасное заполнение значения:


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

Если в базе-источнике реквизит гарантированно существует, код можно сократить до одной строки:

Значение = Источник.Лот;

Шаг 3. Безопасный прием данных на стороне загрузки (в приемнике)

На стороне загрузки переданный параметр будет доступен в обработчиках ПКО через коллекцию ПараметрыОбъекта. Эта коллекция представляет собой Соответствие.

Поскольку наши правила используются для множества баз, а новый реквизит добавлен только в две из них, прямое присвоение вида Объект.Лот = ПараметрыОбъекта["Лот"] вызовет критическую ошибку «Поле объекта не обнаружено» во всех базах, где конфигурация еще не обновлена.

Чтобы решить эту проблему, перейдем в обработчик события «После загрузки» ПКО и напишем универсальный код:


Если ПараметрыОбъекта <> Неопределено Тогда
    
    // Получаем переданный параметр из соответствия
    ЗначениеЛот = ПараметрыОбъекта.Получить("Лот");
    
    Если ЗначениеЛот <> Неопределено Тогда
        // Проверяем, существует ли реквизит в текущей базе-приемнике
        МетаданныеОбъекта = Объект.Метаданные();
        Если МетаданныеОбъекта.Реквизиты.Найти("Лот") <> Неопределено Тогда
            // Реквизит найден в метаданных — безопасно заполняем его
            Объект.Лот = ЗначениеЛот;
        КонецЕсли;
    КонецЕсли;
    
КонецЕсли;

Преимущества данного подхода

Рассмотренный метод обладает рядом существенных преимуществ:

← На главную