Как получить строковое представление перечисления в запросе 1С?

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

При работе с запросами в 1С часто возникает задача получить не только само значение поля, но и его понятное пользователю представление. Быстрый анализ данных требует формирования читаемых отчетов, и если для ссылочных типов (справочников, документов) отлично подходит функция языка запросов ПРЕДСТАВЛЕНИЕ(), то при попытке применить ее к полю типа "Перечисление" система вернет ошибку. Проблема в том, что эта функция не предназначена для работы с перечислениями.

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

Решение 1: Использование конструкции ВЫБОР КОГДА

Самый быстрый и очевидный способ получить представление — это жестко "закодировать" все возможные варианты с помощью оператора ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ. Этот метод идеально подходит, когда у перечисления небольшое и фиксированное количество значений, которые вряд ли будут меняться в будущем.

Рассмотрим на примере. Допустим, у нас есть документ "ЗаказКлиента" с реквизитом "Статус" типа Перечисление.СтатусыЗаказа. В перечислении есть три значения: "Новый", "ВРаботе", "Выполнен".

Чтобы получить их строковые представления в запросе, напишем следующую конструкцию (проверить работу которой поможет Консоль запросов УФ, поддерживающая пакетные запросы):


ВЫБРАТЬ
    ЗаказКлиента.Ссылка,
    ВЫБОР
        КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Новый) ТОГДА "Новый"
        КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.ВРаботе) ТОГДА "В работе"
        КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Выполнен) ТОГДА "Выполнен"
        ИНАЧЕ "Неизвестный статус"
    КОНЕЦ КАК СтатусПредставление
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента

В этом запросе мы явно проверяем значение поля ЗаказКлиента.Статус и для каждого возможного значения возвращаем нужную строку. Секция ИНАЧЕ служит для подстраховки на случай, если появятся новые статусы, которые мы не учли в запросе.

Преимущества метода:

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

Недостатки метода:

  1. Отсутствие масштабируемости: если в перечислении 10, 20 или 50 значений, конструкция ВЫБОР КОГДА станет громоздкой и неудобной в поддержке.
  2. "Хардкод": при добавлении нового значения в перечисление (например, "Отменен") придется вручную исправлять все запросы, где используется эта конструкция. Если этого не сделать, новые значения будут отображаться как "Неизвестный статус".

Вывод: используйте этот метод для перечислений с малым (до 5) и статичным набором значений.

Решение 2: Универсальный метод с использованием временной таблицы (ВТ)

Этот способ является более профессиональным и гибким. Его суть заключается в том, чтобы программно, перед выполнением основного запроса, создать таблицу соответствий "значение перечисления — его представление" и поместить ее во временную таблицу. Затем в основном запросе мы просто соединяем нашу таблицу данных с этой временной таблицей.

Этот метод полностью автоматизирован и не требует правок кода при изменении состава значений перечисления.

Разберем по шагам:

  1. Создаем таблицу значений (ТЗ) в коде 1С. В этой ТЗ будет две колонки: одна для ссылки на значение перечисления, вторая — для его строкового представления.
  2. Заполняем ТЗ данными из метаданных. Мы программно перебираем все значения нужного нам перечисления, получаем для каждого его ссылку и синоним, и добавляем новую строку в ТЗ.
  3. Помещаем ТЗ во временную таблицу. С помощью отдельного запроса и менеджера временных таблиц мы создаем ВТ на основе нашей ТЗ. Стоит учитывать, что в современных версиях платформы (8.3.25+) реализовано добавление данных в существующую временную таблицу, что дает еще больше гибкости при работе с пакетами запросов.
  4. Соединяем основную таблицу с ВТ. В основном запросе используем ЛЕВОЕ СОЕДИНЕНИЕ для того, чтобы к каждой строке с заказом "подтянуть" нужное представление статуса из нашей ВТ.

Посмотрим на пример кода:

Сначала подготовим временную таблицу. Этот код выполняется на языке 1С перед основным запросом.


// Создаем менеджер временных таблиц, который будет управлять нашими ВТ
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

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

// Программно перебираем все значения перечисления из метаданных
Для Каждого ЗначениеПеречисления Из Метаданные.Перечисления.СтатусыЗаказа.ЗначенияПеречисления Цикл
    НоваяСтрока = ТЗ_Статусы.Добавить();
    // Получаем ссылку на значение перечисления по его имени
    НоваяСтрока.Статус = Перечисления.СтатусыЗаказа[ЗначениеПеречисления.Имя];
    
    // Получаем синоним. Если он не задан, берем имя значения
    НоваяСтрока.Представление = ЗначениеПеречисления.Синоним;
    Если ПустаяСтрока(НоваяСтрока.Представление) Тогда
        НоваяСтрока.Представление = ЗначениеПеречисления.Имя;
    КонецЕсли;
КонецЦикла;

// Теперь создаем запрос для помещения нашей ТЗ во временную таблицу
ЗапросДляВТ = Новый Запрос;
ЗапросДляВТ.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
ЗапросДляВТ.Текст =
"ВЫБРАТЬ
|   Статусы.Статус КАК Статус,
|   Статусы.Представление КАК Представление
|ПОМЕСТИТЬ ВТ_Статусы
|ИЗ
|   &ТЗ_Статусы КАК Статусы";

// Передаем нашу заполненную ТЗ в качестве параметра в запрос
ЗапросДляВТ.УстановитьПараметр("ТЗ_Статусы", ТЗ_Статусы);
ЗапросДляВТ.Выполнить();

После выполнения этого кода у нас в памяти будет существовать временная таблица ВТ_Статусы, доступная для последующих запросов, использующих тот же менеджер временных таблиц.

Теперь напишем основной запрос, который будет использовать эту ВТ:


ОсновнойЗапрос = Новый Запрос;
// Обязательно используем тот же менеджер ВТ!
ОсновнойЗапрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;

ОсновнойЗапрос.Текст =
"ВЫБРАТЬ
|    ЗаказКлиента.Ссылка,
|    ЗаказКлиента.Дата,
|    ЗаказКлиента.СуммаДокумента,
|    ЕСТЬNULL(ВТ_Статусы.Представление, ""Статус не найден"") КАК СтатусПредставление
|ИЗ
|    Документ.ЗаказКлиента КАК ЗаказКлиента
|        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Статусы КАК ВТ_Статусы
|        ПО ЗаказКлиента.Статус = ВТ_Статусы.Статус";
        
Результат = ОсновнойЗапрос.Выполнить().Выгрузить();

Обратите внимание на конструкцию ЛЕВОЕ СОЕДИНЕНИЕ. Она позволяет нам связать каждую запись из документа ЗаказКлиента с соответствующей строкой из нашей временной таблицы ВТ_Статусы по полю Статус.

Преимущества метода:

  1. Масштабируемость и гибкость: код будет работать для любого количества значений в перечислении.
  2. Автоматическое обновление: при добавлении, изменении или удалении значений в конфигураторе, код не потребует никаких изменений.
  3. Централизованная логика: код подготовки ВТ можно вынести в общую функцию и переиспользовать.

Недостатки метода:

  1. Более сложный код: требует больше строк кода и понимания работы с менеджером временных таблиц.
  2. Небольшое снижение производительности при инициализации: на создание временной таблицы тратится время, однако это компенсируется скоростью соединения на больших объемах данных.

Когда какой метод использовать?

Подведем итог и сформулируем простое правило выбора:

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

← На главную