К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как получить значение перечисления в 1С

Как получить значение перечисления в 1С: обращение через менеджер, по имени и индексу, проверка значения, работа в запросах и на форме. Примеры кода и типичные ошибки.

Перечисление в 1С — это предопределённый на конфигурационном уровне список значений: статусы документов, виды операций, варианты налогообложения и тому подобное. Значения перечисления задаются разработчиком в конфигураторе и не могут редактироваться пользователем в режиме предприятия, поэтому работа с ними в коде имеет свои особенности по сравнению со справочниками.

Получить значение перечисления можно несколькими способами: прямым обращением через менеджер перечисления, по строковому имени, по индексу, а также в запросе. Выбор способа зависит от задачи: известно ли имя значения на этапе написания кода, приходит ли оно извне (из файла, формы, веб-сервиса) или нужно перебрать все значения списка.

Ниже разобраны основные приёмы с примерами кода на встроенном языке 1С, способы проверки и сравнения значений, работа в запросах и типичные ошибки, которые приводят к неопределённым значениям и трудноуловимым сбоям в обменах данными.

Обращение к значению перечисления напрямую

Самый надёжный способ — прямое обращение через менеджер перечисления, когда имя значения известно на этапе разработки. Синтаксис выглядит так:

Статус = Перечисления.СтатусыЗаказов.ВРаботе;

ВидОперации = Перечисления.ВидыОпераций.Поступление;

Такое обращение проверяется компилятором: если значение переименуют в конфигураторе, при обновлении конфигурации вы получите ошибку ещё до запуска. Это главное преимущество прямого обращения перед строковыми методами — ошибка обнаруживается сразу, а не в момент обработки конкретных данных.

Аналогично работает синтаксис через объект метаданных: Перечисления["СтатусыЗаказов"].ВРаботе. Имя перечисления здесь задано строкой, но имя значения — по-прежнему явно. Такой вариант удобен, когда перечисление выбирается динамически, а значение фиксировано.

Получение значения по имени строкой

Когда имя значения приходит извне — из файла обмена, HTTP-запроса, параметра настройки — обращение выполняется через квадратные скобки:

ИмяЗначения = "ВРаботе"; // получено из внешнего источника

Статус = Перечисления.СтатусыЗаказов[ИмяЗначения];

Если значения с таким именем нет, результатом будет Неопределено, а не исключение. Это источник скрытых ошибок: код не падает, но дальше по логике работает пустое значение. Поэтому результат строкового обращения всегда проверяйте:

Статус = Перечисления.СтатусыЗаказов[ИмяЗначения];

Если Статус = Неопределено Тогда

ВызватьИсключение "Неизвестное значение перечисления: " + ИмяЗначения;

КонецЕсли;

Для более строгого контроля используют метод ЗначениеПеречисленияПоИмени из общих модулей или функцию XMLЗначение при разборе данных обмена: XMLЗначение(Тип("ПеречислениеСсылка.СтатусыЗаказов"), ИмяЗначения). Этот приём стандартен для механизмов сериализации.

Типичные ошибки
01
Обращение по строке без проверки на Неопределено — дальше по коду работает пустое значение, и ошибка всплывает в неожиданном месте
02
Сравнение значения перечисления со строкой: Статус = "ВРаботе" всегда ложно, потому что типы разные
03
Использование синонима (представления) вместо имени значения — синоним может меняться, а имя нет

Перебор всех значений и получение по индексу

Иногда нужно получить не конкретное значение, а весь список — например, для заполнения выпадающего списка на форме или проверки допустимости. Перебор выполняется через цикл по менеджеру:

Для Каждого ЗначениеПеречисления Из Перечисления.СтатусыЗаказов Цикл

Сообщить(ЗначениеПеречисления);

КонецЦикла;

Обращение по индексу возможно: Перечисления.СтатусыЗаказов[0] вернёт первое значение списка. Однако полагаться на индекс в прикладной логике опасно: порядок значений меняется при редактировании конфигурации, и код начнёт возвращать другой статус без каких-либо сообщений об ошибке.

Для получения представления (синонима) значения, которое увидит пользователь, используют простое преобразование Строка(ЗначениеПеречисления) или метод Представление(). Имя же значения в метаданных получают через XMLСтрока(ЗначениеПеречисления) — это стандартный способ выгрузить внутреннее имя для журналирования или обмена.

bsl
ИмяЗначения = XMLСтрока(Перечисления.СтатусыЗаказов.ВРаботе); // "ВРаботе"
ЗначениеОбратно = XMLЗначение(Тип("ПеречислениеСсылка.СтатусыЗаказов"), ИмяЗначения);

Проверка и сравнение значений перечисления

Сравнение значений перечисления выполняется обычным оператором равенства — это ссылочный тип, но сравнение идёт по значению внутри одного вида перечисления:

Если Документ.Статус = Перечисления.СтатусыЗаказов.ВРаботе Тогда

// логика обработки

КонецЕсли;

Для проверки на пустое значение используют функцию ЗначениеЗаполнено() или сравнение с пустой ссылкой: Перечисления.СтатусыЗаказов.ПустаяСсылка(). Пустая ссылка перечисления — это не Неопределено: реквизит типа перечисления без присвоенного значения содержит именно пустую ссылку, и проверка на Неопределено её не поймает.

Определить, принадлежит ли произвольное значение конкретному перечислению, можно через тип: ТипЗнч(Значение) = Тип("ПеречислениеСсылка.СтатусыЗаказов"). Это полезно в универсальных процедурах, принимающих параметры разных типов.

Контрольные точки

Как проверить результат

Значение получено по строке из внешнего источника
Норма

Результат не равен Неопределено и принадлежит нужному типу

Тревожный признак

Результат Неопределено — имя не совпадает с метаданными

Сравнение статуса в условии
Норма

Условие срабатывает для ожидаемых документов

Тревожный признак

Условие всегда ложно — вероятно, сравнение со строкой или с пустой ссылкой

Реквизит заполнен после присвоения
Норма

ЗначениеЗаполнено() возвращает Истина

Тревожный признак

Осталась пустая ссылка — присвоение не выполнилось

Значение перечисления в запросах

В языке запросов обращение к значению перечисления выполняется функцией Значение():

ВЫБРАТЬ

Заказы.Ссылка

ИЗ

Документ.ЗаказКлиента КАК Заказы

ГДЕ

Заказы.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.ВРаботе)

Обратите внимание на единственное число внутри Значение() — Перечисление, а не Перечисления как в коде. Это частая причина синтаксической ошибки запроса.

Альтернатива — передать значение параметром: ГДЕ Заказы.Статус = &Статус и Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыЗаказов.ВРаботе). Параметрический вариант предпочтительнее, когда запрос строится динамически или одно и то же значение используется в нескольких местах запроса. Пустая ссылка в запросе получается как ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.ПустаяСсылка).

Сравнение вариантов получения значения

Прямое обращение Перечисления.Имя.Значение

Самый надёжный: проверяется компилятором. Подходит, когда имя известно при разработке

По строке через [ИмяЗначения]

Нужен для внешних данных и обменов. Требует обязательной проверки на Неопределено

По индексу [0]

Только для перебора и служебных задач. В прикладной логике опасен из-за изменения порядка значений

ЗНАЧЕНИЕ() в запросе

Стандарт для отбора в запросах. Для динамических условий лучше параметр запроса

Работа со значениями перечисления на форме

На управляемой форме реквизит типа «перечисление» автоматически отображается полем со списком выбора, содержащим все значения. Чтобы ограничить список, программно заполняют СписокВыбора элемента формы:

Элементы.Статус.СписокВыбора.Очистить();

Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.ВРаботе);

Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.Завершен);

В тонком клиенте и веб-клиенте обращение Перечисления.Имя.Значение доступно и на клиенте, однако обращение по строковому имени через квадратные скобки на клиенте может быть недоступно в зависимости от режима — надёжнее выполнять такое преобразование в серверной процедуре. Это стоит учитывать при построении клиент-серверного взаимодействия.

Итог

Что важно запомнить

Основной способ — Перечисления.ИмяПеречисления.ИмяЗначения, он проверяется компилятором. Строковое обращение требует проверки на Неопределено. В запросах используется ЗНАЧЕНИЕ(Перечисление.Имя.Значение) или параметр. Пустое значение перечисления — это пустая ссылка, а не Неопределено.

Часто задаваемые вопросы

Чем перечисление отличается от справочника при получении значения?

Значения перечисления жёстко заданы в конфигураторе, доступны напрямую через менеджер без запроса к базе данных и не имеют предопределённых элементов в пользовательском смысле. Значения справочника хранятся в базе, и ссылку на них получают поиском по коду, наименованию или GUID. Перечисление быстрее и надёжнее, но не расширяемо пользователем.

Как получить имя значения перечисления строкой для выгрузки в файл?

Используйте функцию XMLСтрока: XMLСтрока(Перечисления.СтатусыЗаказов.ВРаботе) вернёт строку «ВРаботе». Обратное преобразование — XMLЗначение с указанием типа. Обычное Строка() вернёт синоним (представление), который может отличаться от имени и меняться при локализации.

Почему сравнение статуса со строкой не работает?

Значение перечисления — это ссылочный тип ПеречислениеСсылка, а не строка. Выражение Статус = "ВРаботе" всегда ложно из-за различия типов. Сравнивать нужно со значением, полученным через менеджер перечисления.

Как проверить, что реквизиту перечисления не присвоено значение?

Сравните с пустой ссылкой: Реквизит = Перечисления.СтатусыЗаказов.ПустаяСсылка(), либо используйте функцию ЗначениеЗаполнено(Реквизит) — она вернёт Ложь для пустой ссылки. Проверка на Неопределено здесь не подходит.

Можно ли получить значение перечисления, не зная вида перечисления заранее?

Да, через метаданные: перебрать Метаданные.Перечисления, найти нужный вид, затем получить значение через Перечисления[ИмяВида][ИмяЗначения]. Такой подход применяется в универсальных механизмах обмена и обработок, но требует двойной проверки результата на Неопределено.

Работает ли обращение к перечислению на клиенте в управляемом приложении?

Прямое обращение Перечисления.Имя.Значение работает и на клиенте. Обращение по строковому имени и некоторые сервисные методы доступны только на сервере, поэтому преобразования строк в значения перечисления безопаснее выносить в серверные процедуры с директивой &НаСервере.