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