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