Как сконвертировать два разных значения перечисления из разных баз в одно общее значение в базе-приемнике

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

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

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

Причина возникновения ошибки при прямой конвертации

Прежде чем перейти к решениям, проанализируем, почему стандартный подход или простой код могут не работать. Когда мы пишем в обработчике что-то вроде Если Источник = Перечисления.ТипыНоменклатуры.Супермаркеты..., платформа 1С пытается скомпилировать этот код в момент загрузки правил обмена. Если в конкретной базе значения Супермаркеты не существует в метаданных, система выдаст критическую ошибку, и обмен не начнется.

Также важно помнить разницу между Именем значения (которое задается в Конфигураторе) и его Синонимом (представлением). Функция Строка(Значение) часто возвращает именно синоним, который может быть изменен пользователем или зависеть от языка интерфейса, что делает код нестабильным.

Способ 1. Использование функции XMLСтрока в обработчике ПКС

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

  1. Откроем ПКС нужного нам реквизита.
  2. Перейдем в обработчик Перед выгрузкой.
  3. Напишем код, который проверяет строковое имя значения в источнике.

Проанализируем пример кода:


// Получаем внутреннее имя значения перечисления через XMLСтрока
// Это позволит избежать привязки к синонимам и метаданным конкретной базы
ИмяЗначения = XMLСтрока(Источник[ИмяПкс]); 

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

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

Способ 2. Передача значения через параметры объекта

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

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


// Выключаем стандартную выгрузку реквизита
Отказ = Истина;
// Передаем строковый идентификатор в параметрах
ПередатьОбъектВПараметре("ТипСетиСтрокой", XMLСтрока(Источник.ТипМагазина), ПараметрыОбъекта);

Затем в базе-приемнике, в Правиле конвертации объекта (ПКО), нам нужно обработать этот параметр. Лучше всего это сделать в обработчике При загрузке или После загрузки:


Если ПараметрыОбъекта <> Неопределено И ПараметрыОбъекта.Свойство("ТипСетиСтрокой") Тогда
    ИмяИзИсточника = ПараметрыОбъекта["ТипСетиСтрокой"];
    
    Если ИмяИзИсточника = "Супермаркеты" Или ИмяИзИсточника = "НДСГипер" Тогда
        Объект.ТипМагазина = Перечисления.ТипыМагазинов.НДССети;
    Иначе
        // Пытаемся найти значение по имени через метаданные приемника
        Попытка
            Объект.ТипМагазина = Перечисления.ТипыМагазинов[ИмяИзИсточника];
        Исключение
            // Значение не найдено, обрабатываем ошибку или пропускаем
        КонецПопытки;
    КонецЕсли;
КонецЕсли;

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

Способ 3. Программное создание соответствий в ПКЗ

Если вы все же предпочитаете использовать таблицу Конвертация значений, но боитесь ошибок из-за отсутствия метаданных, можно воспользоваться флагом «Выгружать по строковому идентификатору».

Выясним, как это работает:

Однако, это достаточно трудоемкий путь, и Способ 1 через XMLСтрока считается «золотым стандартом» среди разработчиков 1С.

Важные рекомендации по работе с перечислениями

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

  1. Не используйте функцию Строка() для сравнения. Используйте XMLСтрока() или Строка(Источник.ИмяЗначения.Метаданные().Имя). Это гарантирует, что вы сравниваете код из Конфигуратора, а не текст, который видит бухгалтер.
  2. Избегайте жесткого переименования метаданных. Как упоминалось в обсуждении на форуме, автор решил проблему переименованием значения в базе-источнике. Это плохая практика, так как она может «сломать» внешние отчеты, запросы и затруднить будущие обновления конфигурации. Программная подмена в правилах — гораздо более чистое решение.
  3. Универсальность через проверку метаданных. Если вы пишете универсальный код, который должен работать в 10 разных базах, всегда проверяйте существование значения перед обращением к нему:
    
    Если Метаданные.Перечисления.ТипыМагазинов.ЗначенияПеречисления.Найти("НДСГипер") <> Неопределено Тогда
        // Теперь можно безопасно обращаться к Перечисления.ТипыМагазинов.НДСГипер
    КонецЕсли;
    

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

← На главную