Значение перечисления во встроенном языке 1С 8.3: от прямого обращения до выборки в запросе

· 9 мин

Содержание

Значение перечисления в 1С 8.3 выбирают через свойство глобального контекста Перечисления: Перечисления.ВидыКонтрагентов.ЮридическоеЛицо. Если имя известно только как строка, работает обращение по индексу: Перечисления["ВидыКонтрагентов"]["ЮридическоеЛицо"]. В тексте запроса — конструкция ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ЮридическоеЛицо).

Типичная ситуация: разработчик дорабатывает обработку, где надо отобрать только физлиц или поставить статус документа «Отгружен». Пишет Вид = "Физическое лицо", сравнение молча возвращает Ложь, отбор пустой. Способ выбрать перечисление зависит от места: модуль, клиент, запрос, перебор или загрузка из файла.

Как устроено перечисление в метаданных 1С

Перечисление — объект конфигурации с фиксированным набором значений. Значения задаются в Конфигураторе, во вкладке «Данные» объекта, и пользователь не может добавить новое в режиме Предприятия.

У каждого значения есть три атрибута:

  • 🔤 Имя — идентификатор для кода, без пробелов: ЮридическоеЛицо.
  • 🏷️ Синоним — то, что видит пользователь: «Юридическое лицо».
  • 🔢 Порядок — позиция в списке, от него зависит сортировка.

В базе данных значение хранится как ссылка с типом ПеречислениеСсылка.<Имя>. Это не строка и не число. Поэтому сравнивать его можно только с другим значением того же перечисления.

Что нужноЧем пользоватьсяГде работает
Конкретное значение по имениПеречисления.Имя.Значениесервер и клиент
Значение, имя которого в строкеПеречисления[ИмяПеречисления][ИмяЗначения]сервер и клиент
Предопределённое значение на клиентеПредопределенноеЗначение("Перечисление.Имя.Значение")клиент и сервер
Значение в тексте запросаЗНАЧЕНИЕ(Перечисление.Имя.Значение)только запрос
Пустое значениеПеречисления.Имя.ПустаяСсылка()сервер и клиент
Список всех значенийДля Каждого … Из Перечисления.Имя или метаданныесервер и клиент

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

Прямое обращение к значению перечисления в коде

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

Вид = Перечисления.ВидыКонтрагентов.ЮридическоеЛицо;

Если Контрагент.ВидКонтрагента = Перечисления.ВидыКонтрагентов.ФизическоеЛицо Тогда
    // логика для физлиц
КонецЕсли;

Плюсы прямого обращения:

  • ✅ Синтаксический контроль Конфигуратора поймает опечатку в имени ещё до запуска.
  • ✅ Работает контекстная подсказка: после точки видны все значения.
  • ✅ Поиск ссылок на объект находит такие места при рефакторинге.

Пустое значение

Реквизит с типом перечисления, который ещё не заполнили, содержит пустую ссылку. Проверять его надо так:

Если Документ.Статус = Перечисления.СтатусыЗаказов.ПустаяСсылка() Тогда
    Документ.Статус = Перечисления.СтатусыЗаказов.Новый;
КонецЕсли;

// Короче и универсальнее:
Если Не ЗначениеЗаполнено(Документ.Статус) Тогда
    // реквизит не заполнен
КонецЕсли;

ЗначениеЗаполнено() удобна, когда тип реквизита составной и заранее неизвестно, какое перечисление в нём лежит.

Ветвление по значению

Когда от значения зависит несколько веток, цепочка Если … ИначеЕсли растёт быстро. Для пяти-семи значений нагляднее соответствие «значение → результат»:

СтавкиПоВиду = Новый Соответствие;
СтавкиПоВиду.Вставить(Перечисления.ВидыКонтрагентов.ЮридическоеЛицо, 20);
СтавкиПоВиду.Вставить(Перечисления.ВидыКонтрагентов.ФизическоеЛицо, 13);

Ставка = СтавкиПоВиду.Получить(Контрагент.ВидКонтрагента);
Если Ставка = Неопределено Тогда
    ВызватьИсключение "Не задана ставка для вида контрагента";
КонецЕсли;

Ключом соответствия служит сама ссылка, поэтому поиск работает без строк и индексов. Добавили в перечисление новое значение — код не упадёт молча, а сообщит, что для него нет настройки. Цифры здесь условные, только для иллюстрации.

Значение по умолчанию у реквизита

Чтобы новый документ сразу получал нужное значение, не обязательно писать код. В Конфигураторе у реквизита с типом перечисления есть свойство «Значение заполнения»: выберите в нём значение, и оно подставится при создании объекта. Код в обработчике ОбработкаЗаполнения нужен, только если значение зависит от условий — например, от организации или вида операции.

На клиенте

Менеджер перечислений доступен и в клиентском коде, так что Перечисления.ВидыКонтрагентов.ЮридическоеЛицо в модуле формы с директивой &НаКлиенте отработает. В типовых конфигурациях на клиенте чаще пишут через ПредопределенноеЗначение:

&НаКлиенте
Процедура ВидКонтрагентаПриИзменении(Элемент)
    Если Объект.ВидКонтрагента = ПредопределенноеЗначение("Перечисление.ВидыКонтрагентов.ФизическоеЛицо") Тогда
        Элементы.КПП.Видимость = Ложь;
    КонецЕсли;
КонецПроцедуры

Такая запись единообразна для перечислений, предопределённых элементов справочников и планов счетов. Удобно, когда в одной процедуре сравнивают значения разных видов.

Выбор перечисления по имени из строки

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

ИмяПеречисления = "ВидыКонтрагентов";
ИмяЗначения     = "ЮридическоеЛицо";

Вид = Перечисления[ИмяПеречисления][ИмяЗначения];

Отдельной функции Перечисления() во встроенном языке нет — Перечисления здесь свойство глобального контекста, а скобки дают обращение к элементу коллекции.

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

Функция ЗначениеПеречисленияПоИмени(ИмяПеречисления, ИмяЗначения)

    МетаПеречисление = Метаданные.Перечисления.Найти(ИмяПеречисления);
    Если МетаПеречисление = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;

    Если МетаПеречисление.ЗначенияПеречисления.Найти(ИмяЗначения) = Неопределено Тогда
        Возврат Перечисления[ИмяПеречисления].ПустаяСсылка();
    КонецЕсли;

    Возврат Перечисления[ИмяПеречисления][ИмяЗначения];

КонецФункции

Функция возвращает Неопределено, если нет самого перечисления, и пустую ссылку, если нет значения. Вызывающий код различает оба случая.

Синтаксический контроль не проверяет строковые имена. Переименовали значение в Конфигураторе — обращение по строке сломается только во время работы. Используйте этот способ там, где без него нельзя.

Типы, строки и преобразование значений перечисления

Проверка типа

Когда переменная может хранить значения разных типов, тип проверяют через ТипЗнч:

Если ТипЗнч(Значение) = Тип("ПеречислениеСсылка.ВидыКонтрагентов") Тогда
    // это значение нужного перечисления
КонецЕсли;

Если нужно понять, что значение — какое-то перечисление, без уточнения какое, подойдёт Перечисления.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)). Имя перечисления по ссылке даёт метод Метаданные(): Значение.Метаданные().Имя.

Строка и обратно

Здесь два разных результата, и их часто путают:

ВыражениеРезультат для «Юридическое лицо»
Строка(Вид)«Юридическое лицо» — синоним, для показа
XMLСтрока(Вид)«ЮридическоеЛицо» — имя, для хранения и обмена

Синоним меняется при переводе интерфейса и правке конфигурации. Поэтому в файлы, настройки и внешние системы пишут XMLСтрока, а восстанавливают значение через XMLЗначение:

Текст = XMLСтрока(Перечисления.ВидыКонтрагентов.ЮридическоеЛицо);
// Текст = "ЮридическоеЛицо"

Вид = XMLЗначение(Тип("ПеречислениеСсылка.ВидыКонтрагентов"), Текст);

Для пустой ссылки XMLСтрока вернёт пустую строку, и обратное преобразование даст снова пустую ссылку.

Порядковый номер

Менеджер перечисления умеет переводить значение в индекс и обратно — методы Индекс() и Получить(). Нумерация с нуля, по порядку в Конфигураторе.

Номер = Перечисления.ВидыКонтрагентов.Индекс(Вид);   // 0, 1, 2...
Первое = Перечисления.ВидыКонтрагентов.Получить(0);

Хранить индекс во внешних данных не стоит: перенесли значение выше в списке — номера сдвинулись. Для сравнения «раньше/позже» внутри сеанса индекс подходит.

Приведение через описание типов

Если в реквизит с составным типом пришло значение неизвестного типа, ОписаниеТипов.ПривестиЗначение() вернёт пустую ссылку для чужого значения:

ОписаниеВида = Новый ОписаниеТипов("ПеречислениеСсылка.ВидыКонтрагентов");
Вид = ОписаниеВида.ПривестиЗначение(ВходящееЗначение);

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

Менеджер перечисления — коллекция, по нему проходит обычный цикл Для Каждого. Значения идут в порядке, заданном в Конфигураторе.

Список = Новый СписокЗначений;
Для Каждого Вид Из Перечисления.ВидыКонтрагентов Цикл
    Список.Добавить(Вид, Строка(Вид));
КонецЦикла;

Когда кроме ссылки нужны имя и синоним, перебирают метаданные:

МетаЗначения = Метаданные.Перечисления.ВидыКонтрагентов.ЗначенияПеречисления;

Для Каждого МетаЗначение Из МетаЗначения Цикл
    Ссылка = Перечисления.ВидыКонтрагентов[МетаЗначение.Имя];
    Сообщить(МетаЗначение.Имя + " — " + МетаЗначение.Синоним);
КонецЦикла;

Связка метаданных и индекса решает обратную задачу — узнать имя значения по ссылке:

Индекс = Перечисления.ВидыКонтрагентов.Индекс(Вид);
ИмяЗначения = Метаданные.Перечисления.ВидыКонтрагентов.ЗначенияПеречисления[Индекс].Имя;

Для пустой ссылки Индекс() смысла не имеет — проверьте ЗначениеЗаполнено(Вид) до вызова.

Ограничить выбор на форме

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Элементы.Статус.СписокВыбора.Очистить();
    Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.Новый);
    Элементы.Статус.СписокВыбора.Добавить(Перечисления.СтатусыЗаказов.Согласован);
КонецПроцедуры

В списке останутся только два статуса. Остальные значения в данных не пропадают, их просто нельзя выбрать в этом поле.

Как выбрать значение перечисления в запросе

Внутри текста запроса нельзя обратиться к менеджеру Перечисления. Для конкретного значения есть функция языка запросов ЗНАЧЕНИЕ:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Контрагенты.Ссылка,
|    Контрагенты.Наименование
|ИЗ
|    Справочник.Контрагенты КАК Контрагенты
|ГДЕ
|    Контрагенты.ВидКонтрагента = ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ЮридическоеЛицо)";

Пустая ссылка в запросе — ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ПустаяСсылка), без скобок после ПустаяСсылка.

Через параметр

Если значение выбирают в коде, его передают параметром. Так же передают список значений для условия В:

Запрос.Текст =
"ВЫБРАТЬ
|    Заказы.Ссылка
|ИЗ
|    Документ.ЗаказКлиента КАК Заказы
|ГДЕ
|    Заказы.Статус В (&Статусы)";

Статусы = Новый Массив;
Статусы.Добавить(Перечисления.СтатусыЗаказов.Новый);
Статусы.Добавить(Перечисления.СтатусыЗаказов.Согласован);
Запрос.УстановитьПараметр("Статусы", Статусы);

Имена объектов в этих примерах условные. В вашей конфигурации документ и перечисление статусов могут называться иначе — проверьте в дереве метаданных.

Значение перечисления в ВЫБОР КОГДА

ЗНАЧЕНИЕ() работает в любой части запроса, не только в ГДЕ. Например, так считают признак прямо в выборке:

"ВЫБРАТЬ
|    Контрагенты.Ссылка,
|    ВЫБОР
|        КОГДА Контрагенты.ВидКонтрагента = ЗНАЧЕНИЕ(Перечисление.ВидыКонтрагентов.ФизическоеЛицо)
|            ТОГДА ИСТИНА
|        ИНАЧЕ ЛОЖЬ
|    КОНЕЦ КАК ЭтоФизлицо
|ИЗ
|    Справочник.Контрагенты КАК Контрагенты"

Тот же приём годится для группировки: в одном запросе раскладывают суммы по колонкам «юрлица» и «физлица» без постобработки в коде.

Перечисление как таблица запроса

Перечисление можно выбрать как источник данных. Таблица Перечисление.<Имя> содержит поля Ссылка и Порядок:

"ВЫБРАТЬ
|    Виды.Ссылка,
|    ПРЕДСТАВЛЕНИЕ(Виды.Ссылка) КАК Синоним
|ИЗ
|    Перечисление.ВидыКонтрагентов КАК Виды
|УПОРЯДОЧИТЬ ПО
|    Виды.Порядок"

Такая выборка нужна, чтобы получить строки даже для значений, по которым нет данных. Например, отчёт по всем статусам заказов, включая те, где заказов ноль: соедините таблицу перечисления с документами левым соединением.

УПОРЯДОЧИТЬ ПО по полю с типом перечисления сортирует по порядку значений в Конфигураторе, а не по алфавиту синонимов. Нужен алфавит — сортируйте по ПРЕДСТАВЛЕНИЕ(...).

Проверка типа в запросе

В составном реквизите отделить значения перечисления помогает ССЫЛКА:

"ГДЕ
|    Таблица.Значение ССЫЛКА Перечисление.ВидыКонтрагентов"

Ошибки при выборе перечисления и как их найти

Диагностика: выберите симптом

Ещё три ловушки, которые не дают явной ошибки:

  • 👯 Одинаковые имена в разных перечислениях. Значение Новый может быть и в статусах заказов, и в статусах счетов. Это разные ссылки разных типов: сравнение Перечисления.СтатусыЗаказов.Новый = Перечисления.СтатусыСчетов.Новый вернёт Ложь. Следите, из какого перечисления берёте значение, особенно при копировании кода между модулями.

  • 🔁 Удалили значение из перечисления. Ссылки на него в документах становятся битыми. Перед удалением найдите документы и справочники с этим значением и переназначьте их.

  • 🧩 Правите типовую конфигурацию . Новое значение в типовое перечисление лучше не добавлять: обновление конфигурации усложнится. Для своих значений создайте собственное перечисление в расширении.

Частые вопросы

Можно ли добавить значение перечисления из режима Предприятия?
Нет. Набор значений фиксирован в конфигурации. Если пользователи должны пополнять список, нужен справочник, а не перечисление.
Чем перечисление отличается от предопределённого элемента справочника?
У справочника можно добавлять свои элементы и реквизиты. У перечисления только фиксированный список, зато оно легче и не требует заполнения данных.
Как показать синоним значения пользователю?
Через Строка(Значение) в коде или ПРЕДСТАВЛЕНИЕ() в запросе. Синоним берётся из Конфигуратора.
Работает ли Перечисления.Имя.Значение в общем модуле на клиенте?
Да, менеджер перечислений доступен на клиенте. Для единообразия с другими предопределёнными данными можно использовать ПредопределенноеЗначение.
Как узнать, сколько значений в перечислении?
Через метаданные: Метаданные.Перечисления.Имя.ЗначенияПеречисления.Количество().