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