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