При работе с запросами в 1С часто возникает задача получить не только само значение поля, но и его понятное пользователю представление. Быстрый анализ данных требует формирования читаемых отчетов, и если для ссылочных типов (справочников, документов) отлично подходит функция языка запросов ПРЕДСТАВЛЕНИЕ(), то при попытке применить ее к полю типа "Перечисление" система вернет ошибку. Проблема в том, что эта функция не предназначена для работы с перечислениями.
В этой статье мы подробно разберем, как обойти это ограничение и получить текстовое представление (синоним) для значений перечисления непосредственно в запросе. Рассмотрим два основных способа: простой, но ограниченный, и более сложный, но универсальный и масштабируемый.
Самый быстрый и очевидный способ получить представление — это жестко "закодировать" все возможные варианты с помощью оператора ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ. Этот метод идеально подходит, когда у перечисления небольшое и фиксированное количество значений, которые вряд ли будут меняться в будущем.
Рассмотрим на примере. Допустим, у нас есть документ "ЗаказКлиента" с реквизитом "Статус" типа Перечисление.СтатусыЗаказа. В перечислении есть три значения: "Новый", "ВРаботе", "Выполнен".
Чтобы получить их строковые представления в запросе, напишем следующую конструкцию (проверить работу которой поможет Консоль запросов УФ, поддерживающая пакетные запросы):
ВЫБРАТЬ
ЗаказКлиента.Ссылка,
ВЫБОР
КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Новый) ТОГДА "Новый"
КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.ВРаботе) ТОГДА "В работе"
КОГДА ЗаказКлиента.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Выполнен) ТОГДА "Выполнен"
ИНАЧЕ "Неизвестный статус"
КОНЕЦ КАК СтатусПредставление
ИЗ
Документ.ЗаказКлиента КАК ЗаказКлиента
В этом запросе мы явно проверяем значение поля ЗаказКлиента.Статус и для каждого возможного значения возвращаем нужную строку. Секция ИНАЧЕ служит для подстраховки на случай, если появятся новые статусы, которые мы не учли в запросе.
Преимущества метода:
Недостатки метода:
ВЫБОР КОГДА станет громоздкой и неудобной в поддержке.Вывод: используйте этот метод для перечислений с малым (до 5) и статичным набором значений.
Этот способ является более профессиональным и гибким. Его суть заключается в том, чтобы программно, перед выполнением основного запроса, создать таблицу соответствий "значение перечисления — его представление" и поместить ее во временную таблицу. Затем в основном запросе мы просто соединяем нашу таблицу данных с этой временной таблицей.
Этот метод полностью автоматизирован и не требует правок кода при изменении состава значений перечисления.
Разберем по шагам:
ЛЕВОЕ СОЕДИНЕНИЕ для того, чтобы к каждой строке с заказом "подтянуть" нужное представление статуса из нашей ВТ.Посмотрим на пример кода:
Сначала подготовим временную таблицу. Этот код выполняется на языке 1С перед основным запросом.
// Создаем менеджер временных таблиц, который будет управлять нашими ВТ
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Создаем таблицу значений для хранения пар "Значение - Представление"
ТЗ_Статусы = Новый ТаблицаЗначений;
ТЗ_Статусы.Колонки.Добавить("Статус", Новый ОписаниеТипов("ПеречислениеСсылка.СтатусыЗаказа"));
ТЗ_Статусы.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100)));
// Программно перебираем все значения перечисления из метаданных
Для Каждого ЗначениеПеречисления Из Метаданные.Перечисления.СтатусыЗаказа.ЗначенияПеречисления Цикл
НоваяСтрока = ТЗ_Статусы.Добавить();
// Получаем ссылку на значение перечисления по его имени
НоваяСтрока.Статус = Перечисления.СтатусыЗаказа[ЗначениеПеречисления.Имя];
// Получаем синоним. Если он не задан, берем имя значения
НоваяСтрока.Представление = ЗначениеПеречисления.Синоним;
Если ПустаяСтрока(НоваяСтрока.Представление) Тогда
НоваяСтрока.Представление = ЗначениеПеречисления.Имя;
КонецЕсли;
КонецЦикла;
// Теперь создаем запрос для помещения нашей ТЗ во временную таблицу
ЗапросДляВТ = Новый Запрос;
ЗапросДляВТ.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
ЗапросДляВТ.Текст =
"ВЫБРАТЬ
| Статусы.Статус КАК Статус,
| Статусы.Представление КАК Представление
|ПОМЕСТИТЬ ВТ_Статусы
|ИЗ
| &ТЗ_Статусы КАК Статусы";
// Передаем нашу заполненную ТЗ в качестве параметра в запрос
ЗапросДляВТ.УстановитьПараметр("ТЗ_Статусы", ТЗ_Статусы);
ЗапросДляВТ.Выполнить();
После выполнения этого кода у нас в памяти будет существовать временная таблица ВТ_Статусы, доступная для последующих запросов, использующих тот же менеджер временных таблиц.
Теперь напишем основной запрос, который будет использовать эту ВТ:
ОсновнойЗапрос = Новый Запрос;
// Обязательно используем тот же менеджер ВТ!
ОсновнойЗапрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
ОсновнойЗапрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиента.Ссылка,
| ЗаказКлиента.Дата,
| ЗаказКлиента.СуммаДокумента,
| ЕСТЬNULL(ВТ_Статусы.Представление, ""Статус не найден"") КАК СтатусПредставление
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Статусы КАК ВТ_Статусы
| ПО ЗаказКлиента.Статус = ВТ_Статусы.Статус";
Результат = ОсновнойЗапрос.Выполнить().Выгрузить();
Обратите внимание на конструкцию ЛЕВОЕ СОЕДИНЕНИЕ. Она позволяет нам связать каждую запись из документа ЗаказКлиента с соответствующей строкой из нашей временной таблицы ВТ_Статусы по полю Статус.
Преимущества метода:
Недостатки метода:
Подведем итог и сформулируем простое правило выбора:
ВЫБОР КОГДА.В большинстве случаев разработки сложных систем предпочтение отдается второму методу.