Значение перечисления во встроенном языке 1С 8.3: от прямого обращения до выборки в запросе
Содержание
Значение перечисления в 1С 8.3 выбирают через свойство глобального контекста Перечисления: Перечисления.ВидыКонтрагентов.ЮридическоеЛицо. Если имя известно только как строка, работает обращение по индексу: Перечисления["ВидыКонтрагентов"]["ЮридическоеЛицо"]. В тексте запроса — конструкция ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ЮридическоеЛицо).
Типичная ситуация: разработчик дорабатывает обработку, где надо отобрать только физлиц или поставить статус документа «Отгружен». Пишет Вид = "Физическое лицо", сравнение молча возвращает Ложь, отбор пустой. Способ выбрать перечисление зависит от места: модуль, клиент, запрос, перебор или загрузка из файла.
Как устроено перечисление в метаданных 1С
Перечисление — объект конфигурации с фиксированным набором значений. Значения задаются в Конфигураторе, во вкладке «Данные» объекта, и пользователь не может добавить новое в режиме Предприятия.
У каждого значения есть три атрибута:
- 🔤 Имя — идентификатор для кода, без пробелов:
ЮридическоеЛицо. - 🏷️ Синоним — то, что видит пользователь: «Юридическое лицо».
- 🔢 Порядок — позиция в списке, от него зависит сортировка.
В базе данных значение хранится как ссылка с типом ПеречислениеСсылка.<Имя>. Это не строка и не число. Поэтому сравнивать его можно только с другим значением того же перечисления.
| Что нужно | Чем пользоваться | Где работает |
|---|---|---|
| Конкретное значение по имени | Перечисления.Имя.Значение | сервер и клиент |
| Значение, имя которого в строке | Перечисления[ИмяПеречисления][ИмяЗначения] | сервер и клиент |
| Предопределённое значение на клиенте | ПредопределенноеЗначение("Перечисление.Имя.Значение") | клиент и сервер |
| Значение в тексте запроса | ЗНАЧЕНИЕ(Перечисление.Имя.Значение) | только запрос |
| Пустое значение | Перечисления.Имя.ПустаяСсылка() | сервер и клиент |
| Список всех значений | Для Каждого … Из Перечисления.Имя или метаданные | сервер и клиент |
В коде пишут Перечисления (множественное число), а в запросе и в ПредопределенноеЗначение — Перечисление (единственное). Путаница в одной букве — частая причина синтаксических ошибок.
Прямое обращение к значению перечисления в коде
Самый частый способ — через менеджер перечисления. Цепочка из трёх частей: коллекция Перечисления, имя перечисления, имя значения.
Вид = Перечисления.ВидыКонтрагентов.ЮридическоеЛицо;
Если Контрагент.ВидКонтрагента = Перечисления.ВидыКонтрагентов.ФизическоеЛицо Тогда
// логика для физлиц
КонецЕсли;
Плюсы прямого обращения:
- ✅ Синтаксический контроль Конфигуратора поймает опечатку в имени ещё до запуска.
- ✅ Работает контекстная подсказка: после точки видны все значения.
- ✅ Поиск ссылок на объект находит такие места при рефакторинге.
Пустое значение
Реквизит с типом перечисления, который ещё не заполнили, содержит пустую ссылку. Проверять его надо так:
Если Документ.Статус = Перечисления.СтатусыЗаказов.ПустаяСсылка() Тогда
Документ.Статус = Перечисления.СтатусыЗаказов.Новый;
КонецЕсли;
// Короче и универсальнее:
Если Не ЗначениеЗаполнено(Документ.Статус) Тогда
// реквизит не заполнен
КонецЕсли;
ЗначениеЗаполнено() удобна, когда тип реквизита составной и заранее неизвестно, какое перечисление в нём лежит.
Ветвление по значению
Когда от значения зависит несколько веток, цепочка Если … ИначеЕсли растёт быстро. Для пяти-семи значений нагляднее соответствие «значение → результат»:
СтавкиПоВиду = Новый Соответствие;
СтавкиПоВиду.Вставить(Перечисления.ВидыКонтрагентов.ЮридическоеЛицо, 20);
СтавкиПоВиду.Вставить(Перечисления.ВидыКонтрагентов.ФизическоеЛицо, 13);
Ставка = СтавкиПоВиду.Получить(Контрагент.ВидКонтрагента);
Если Ставка = Неопределено Тогда
ВызватьИсключение "Не задана ставка для вида контрагента";
КонецЕсли;
Ключом соответствия служит сама ссылка, поэтому поиск работает без строк и индексов. Добавили в перечисление новое значение — код не упадёт молча, а сообщит, что для него нет настройки. Цифры здесь условные, только для иллюстрации.
Значение по умолчанию у реквизита
Чтобы новый документ сразу получал нужное значение, не обязательно писать код. В Конфигураторе у реквизита с типом перечисления есть свойство «Значение заполнения»: выберите в нём значение, и оно подставится при создании объекта. Код в обработчике ОбработкаЗаполнения нужен, только если значение зависит от условий — например, от организации или вида операции.
На клиенте
Менеджер перечислений доступен и в клиентском коде, так что Перечисления.ВидыКонтрагентов.ЮридическоеЛицо в модуле формы с директивой &НаКлиенте отработает. В типовых конфигурациях на клиенте чаще пишут через ПредопределенноеЗначение:
&НаКлиенте
Процедура ВидКонтрагентаПриИзменении(Элемент)
Если Объект.ВидКонтрагента = ПредопределенноеЗначение("Перечисление.ВидыКонтрагентов.ФизическоеЛицо") Тогда
Элементы.КПП.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Такая запись единообразна для перечислений, предопределённых элементов справочников и планов счетов. Удобно, когда в одной процедуре сравнивают значения разных видов.
Выбор перечисления по имени из строки
Иногда имя значения приходит строкой: из настроек, из файла обмена, из параметра общей процедуры. Тогда точка не подходит, нужен доступ по индексу. Коллекция Перечисления и менеджер конкретного перечисления поддерживают квадратные скобки.
ИмяПеречисления = "ВидыКонтрагентов";
ИмяЗначения = "ЮридическоеЛицо";
Вид = Перечисления[ИмяПеречисления][ИмяЗначения];
Отдельной функции Перечисления() во встроенном языке нет — Перечисления здесь свойство глобального контекста, а скобки дают обращение к элементу коллекции.
Если имени нет в метаданных, строка падает с ошибкой выполнения. Поэтому строку, пришедшую извне, сначала проверяют:
Функция ЗначениеПеречисленияПоИмени(ИмяПеречисления, ИмяЗначения)
МетаПеречисление = Метаданные.Перечисления.Найти(ИмяПеречисления);
Если МетаПеречисление = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если МетаПеречисление.ЗначенияПеречисления.Найти(ИмяЗначения) = Неопределено Тогда
Возврат Перечисления[ИмяПеречисления].ПустаяСсылка();
КонецЕсли;
Возврат Перечисления[ИмяПеречисления][ИмяЗначения];
КонецФункции
Функция возвращает Неопределено, если нет самого перечисления, и пустую ссылку, если нет значения. Вызывающий код различает оба случая.
Синтаксический контроль не проверяет строковые имена. Переименовали значение в Конфигураторе — обращение по строке сломается только во время работы. Используйте этот способ там, где без него нельзя.
Типы, строки и преобразование значений перечисления
Проверка типа
Когда переменная может хранить значения разных типов, тип проверяют через ТипЗнч:
Если ТипЗнч(Значение) = Тип("ПеречислениеСсылка.ВидыКонтрагентов") Тогда
// это значение нужного перечисления
КонецЕсли;
Если нужно понять, что значение — какое-то перечисление, без уточнения какое, подойдёт Перечисления.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)). Имя перечисления по ссылке даёт метод Метаданные(): Значение.Метаданные().Имя.
Строка и обратно
Здесь два разных результата, и их часто путают:
| Выражение | Результат для «Юридическое лицо» |
|---|---|
Строка(Вид) | «Юридическое лицо» — синоним, для показа |
XMLСтрока(Вид) | «ЮридическоеЛицо» — имя, для хранения и обмена |
Синоним меняется при переводе интерфейса и правке конфигурации. Поэтому в файлы, настройки и внешние системы пишут XMLСтрока, а восстанавливают значение через XMLЗначение:
Текст = XMLСтрока(Перечисления.ВидыКонтрагентов.ЮридическоеЛицо);
// Текст = "ЮридическоеЛицо"
Вид = XMLЗначение(Тип("ПеречислениеСсылка.ВидыКонтрагентов"), Текст);
Для пустой ссылки XMLСтрока вернёт пустую строку, и обратное преобразование даст снова пустую ссылку.
Порядковый номер
Менеджер перечисления умеет переводить значение в индекс и обратно — методы Индекс() и Получить(). Нумерация с нуля, по порядку в Конфигураторе.
Номер = Перечисления.ВидыКонтрагентов.Индекс(Вид); // 0, 1, 2...
Первое = Перечисления.ВидыКонтрагентов.Получить(0);
Хранить индекс во внешних данных не стоит: перенесли значение выше в списке — номера сдвинулись. Для сравнения «раньше/позже» внутри сеанса индекс подходит.
Приведение через описание типов
Если в реквизит с составным типом пришло значение неизвестного типа, ОписаниеТипов.ПривестиЗначение() вернёт пустую ссылку для чужого значения:
ОписаниеВида = Новый ОписаниеТипов("ПеречислениеСсылка.ВидыКонтрагентов");
Вид = ОписаниеВида.ПривестиЗначение(ВходящееЗначение);
Перебор всех значений перечисления
Менеджер перечисления — коллекция, по нему проходит обычный цикл Для Каждого. Значения идут в порядке, заданном в Конфигураторе.
Список = Новый СписокЗначений;
Для Каждого Вид Из Перечисления.ВидыКонтрагентов Цикл
Список.Добавить(Вид, Строка(Вид));
КонецЦикла;
Когда кроме ссылки нужны имя и синоним, перебирают метаданные:
МетаЗначения = Метаданные.Перечисления.ВидыКонтрагентов.ЗначенияПеречисления;
Для Каждого МетаЗначение Из МетаЗначения Цикл
Ссылка = Перечисления.ВидыКонтрагентов[МетаЗначение.Имя];
Сообщить(МетаЗначение.Имя + " — " + МетаЗначение.Синоним);
КонецЦикла;
Связка метаданных и индекса решает обратную задачу — узнать имя значения по ссылке:
Индекс = Перечисления.ВидыКонтрагентов.Индекс(Вид);
ИмяЗначения = Метаданные.Перечисления.ВидыКонтрагентов.ЗначенияПеречисления[Индекс].Имя;
Для пустой ссылки Индекс() смысла не имеет — проверьте ЗначениеЗаполнено(Вид) до вызова.
Ограничить выбор на форме
Пользователь выбирает значение из выпадающего списка поля формы. Если нужны не все значения, заполните у элемента формы список выбора программно:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элементы.Статус.СписокВыбора.Очистить();
Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.Новый);
Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.Согласован);
КонецПроцедуры
В списке останутся только два статуса. Остальные значения в данных не пропадают, их просто нельзя выбрать в этом поле.
Как выбрать значение перечисления в запросе
Внутри текста запроса нельзя обратиться к менеджеру Перечисления. Для конкретного значения есть функция языка запросов ЗНАЧЕНИЕ:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка,
| Контрагенты.Наименование
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ВидКонтрагента = ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ЮридическоеЛицо)";
Пустая ссылка в запросе — ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ПустаяСсылка), без скобок после ПустаяСсылка.
Через параметр
Если значение выбирают в коде, его передают параметром. Так же передают список значений для условия В:
Запрос.Текст =
"ВЫБРАТЬ
| Заказы.Ссылка
|ИЗ
| Документ.ЗаказКлиента КАК Заказы
|ГДЕ
| Заказы.Статус В (&Статусы)";
Статусы = Новый Массив;
Статусы.Добавить(Перечисления.СтатусыЗаказов.Новый);
Статусы.Добавить(Перечисления.СтатусыЗаказов.Согласован);
Запрос.УстановитьПараметр("Статусы", Статусы);
Имена объектов в этих примерах условные. В вашей конфигурации документ и перечисление статусов могут называться иначе — проверьте в дереве метаданных.
Значение перечисления в ВЫБОР КОГДА
ЗНАЧЕНИЕ() работает в любой части запроса, не только в ГДЕ. Например, так считают признак прямо в выборке:
"ВЫБРАТЬ
| Контрагенты.Ссылка,
| ВЫБОР
| КОГДА Контрагенты.ВидКонтрагента = ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ФизическоеЛицо)
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ЭтоФизлицо
|ИЗ
| Справочник.Контрагенты КАК Контрагенты"
Тот же приём годится для группировки: в одном запросе раскладывают суммы по колонкам «юрлица» и «физлица» без постобработки в коде.
Перечисление как таблица запроса
Перечисление можно выбрать как источник данных. Таблица Перечисление.<Имя> содержит поля Ссылка и Порядок:
"ВЫБРАТЬ
| Виды.Ссылка,
| ПРЕДСТАВЛЕНИЕ(Виды.Ссылка) КАК Синоним
|ИЗ
| Перечисление.ВидыКонтрагентов КАК Виды
|УПОРЯДОЧИТЬ ПО
| Виды.Порядок"
Такая выборка нужна, чтобы получить строки даже для значений, по которым нет данных. Например, отчёт по всем статусам заказов, включая те, где заказов ноль: соедините таблицу перечисления с документами левым соединением.
УПОРЯДОЧИТЬ ПО по полю с типом перечисления сортирует по порядку значений в Конфигураторе, а не по алфавиту синонимов. Нужен алфавит — сортируйте по ПРЕДСТАВЛЕНИЕ(...).
Проверка типа в запросе
В составном реквизите отделить значения перечисления помогает ССЫЛКА:
"ГДЕ
| Таблица.Значение ССЫЛКА Перечисление.ВидыКонтрагентов"
Ошибки при выборе перечисления и как их найти
Вид = "Юридическое лицо". Значение перечисления — ссылка, а не текст. Сравнивайте с Перечисления.ВидыКонтрагентов.ЮридическоеЛицо или переводите строку через XMLЗначение.Метаданные.Перечисления.Имя.ЗначенияПеречисления.Найти() перед обращением.Перечисления вместо Перечисление или скобки после ПустаяСсылка. В запросе: ЗНАЧЕНИЕ(Перечисление.Имя.ПустаяСсылка).ТипЗнч и добавьте условие на ЗНАЧЕНИЕ(Перечисление.Имя.ПустаяСсылка), если пустые нужно учитывать.Строка()) или индексы, а их изменили. Перейдите на XMLСтрока и XMLЗначение — они опираются на имя.Ещё три ловушки, которые не дают явной ошибки:
👯 Одинаковые имена в разных перечислениях. Значение
Новыйможет быть и в статусах заказов, и в статусах счетов. Это разные ссылки разных типов: сравнениеПеречисления.СтатусыЗаказов.Новый = Перечисления.СтатусыСчетов.НовыйвернётЛожь. Следите, из какого перечисления берёте значение, особенно при копировании кода между модулями.🔁 Удалили значение из перечисления. Ссылки на него в документах становятся битыми. Перед удалением найдите документы и справочники с этим значением и переназначьте их.
🧩 Правите типовую конфигурацию . Новое значение в типовое перечисление лучше не добавлять: обновление конфигурации усложнится. Для своих значений создайте собственное перечисление в расширении.
Частые вопросы
Можно ли добавить значение перечисления из режима Предприятия?
Чем перечисление отличается от предопределённого элемента справочника?
Как показать синоним значения пользователю?
Строка(Значение) в коде или ПРЕДСТАВЛЕНИЕ() в запросе. Синоним берётся из Конфигуратора.Работает ли Перечисления.Имя.Значение в общем модуле на клиенте?
ПредопределенноеЗначение.Как узнать, сколько значений в перечислении?
Метаданные.Перечисления.Имя.ЗначенияПеречисления.Количество().