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

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

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

Как получить ссылку на значение перечисления в 1С: через Перечисления.Имя.Значение, ПредопределенноеЗначение, НайтиПоНаименованию. Примеры кода и типичные ошибки.

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

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

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

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

Ставка = Перечисления.СтавкиНДС.НДС20;

ДокументОбъект.СтавкаНДС = Ставка;

Имя перечисления и имя значения берутся из конфигуратора — это те самые идентификаторы, которые задал разработчик при создании объекта. Важно: используется именно имя (идентификатор), а не синоним, который видит пользователь. Если синоним «НДС 20%», а имя «НДС20», в коде пишется «НДС20».

Преимущество прямого обращения — контроль на этапе компиляции. Если значение переименуют или удалят в конфигураторе, модуль не пройдёт проверку синтаксиса, и ошибку заметят сразу, а не в рабочей базе. Поэтому этот способ предпочтителен везде, где имя значения известно заранее.

Получение значения по строке: ПредопределенноеЗначение

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

ИмяЗначения = "НДС20";

Ставка = ПредопределенноеЗначение("Перечисление.СтавкиНДС." + ИмяЗначения);

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

Обратите внимание: путь строится по шаблону «Перечисление.ИмяПеречисления.ИмяЗначения» — именно в единственном числе «Перечисление», в отличие от коллекции Перечисления в коде. Это частая причина ошибок при копировании шаблонов.

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

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

МетаЗначения = Метаданные.Перечисления.СтавкиНДС.ЗначенияПеречисления;

Для Каждого МетаЗначение Из МетаЗначения Цикл

Если МетаЗначение.Синоним = ИскомыйСиноним Тогда

Результат = Перечисления.СтавкиНДС[МетаЗначение.Имя];

Прервать;

КонецЕсли;

КонецЦикла;

Здесь используется ещё один полезный приём — обращение к значению по индексу или имени через квадратные скобки: Перечисления.СтавкиНДС["НДС20"] или Перечисления.СтавкиНДС[МетаЗначение.Имя]. Это альтернатива ПредопределенноеЗначение для случаев, когда имя уже есть в переменной.

Для перебора всех значений перечисления в пользовательских целях (например, заполнение списка выбора на форме) удобнее метод ПолучитьЗначенияПеречисления у менеджера или обход коллекции:

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

СписокВыбора.Добавить(Значение, Строка(Значение));

КонецЦикла;

Ссылка на перечисление в запросе

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

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.СтавкаНДС = &Ставка";

Запрос.УстановитьПараметр("Ставка", Перечисления.СтавкиНДС.НДС20);

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

Маршрут решения

Как выбрать способ

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

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

Присвоение ссылки на перечисление реквизиту объекта ничем не отличается от других типов: Объект.Реквизит = Перечисления.ВидыОпераций.Продажа;. Особенность в другом — у перечисления есть понятие пустой ссылки. Если реквизит не заполнен, он содержит Перечисления.ИмяПеречисления.ПустаяСсылка, а не Неопределено.

Проверку на пустое значение корректно делать через функцию ЗначениеЗаполнено() или сравнение с пустой ссылкой:

Если НЕ ЗначениеЗаполнено(Объект.СтавкаНДС) Тогда

Объект.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;

КонецЕсли;

Сравнение значений перечислений выполняется обычным оператором равенства — Если Объект.ВидОперации = Перечисления.ВидыОпераций.Возврат Тогда. Приводить значение к строке для сравнения не нужно и вредно: Строка(Значение) возвращает синоним, который могут изменить в конфигураторе, и сравнение молча перестанет работать.

Типичные ошибки
01
Сравнение через Строка(Значение) = "НДС 20%" — ломается при смене синонима; сравнивайте ссылки напрямую
02
Обращение по синониму Перечисления.СтавкиНДС["НДС 20%"] — в квадратных скобках указывают имя (идентификатор), а не представление
03
Отсутствие проверки результата ПредопределенноеЗначение — при опечатке в строке в данные уходит Неопределено
04
Попытка создать новое значение перечисления программно — список значений меняется только в конфигураторе
05
Сравнение с Неопределено вместо ПустаяСсылка — незаполненный реквизит типа перечисление содержит пустую ссылку

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

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

Если ТипЗнч(Значение) = Тип("ПеречислениеСсылка.СтавкиНДС") Тогда

// значение корректного типа

КонецЕсли;

В отладчике тип и значение видны сразу: ссылка на перечисление отображается своим синонимом, а в колонке типа указано «ПеречислениеСсылка.ИмяПеречисления». Если вместо значения видите «Неопределено» — ищите ошибку в строке пути или имени значения.

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

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

Тип полученного значения
Норма

ПеречислениеСсылка.ИмяПеречисления

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

Неопределено или Строка — значит, путь или имя указаны неверно

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

В форме объекта реквизит показывает ожидаемое представление

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

Поле пустое — вероятно, записалось Неопределено или пустая ссылка

Результат запроса с параметром-перечислением
Норма

Возвращаются строки с нужным значением реквизита

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

Пустой результат при заведомо подходящих данных — проверьте, тот ли это вид перечисления

Ограничения и частные сценарии

Несколько границ, о которых стоит помнить. Во-первых, значения перечислений нельзя добавлять или изменять в режиме предприятия и программно — только в конфигураторе с последующим обновлением конфигурации базы данных. Если бизнес-процесс требует расширяемого списка, правильнее использовать справочник, а не перечисление.

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

В-третьих, при обмене данными значения перечислений сопоставляются по именам. Если в двух базах одно и то же перечисление имеет разные имена значений, ссылка при загрузке не найдётся, и в зависимости от настроек обмена получится либо пустое значение, либо ошибка. Поэтому при интеграциях имена значений выравнивают заранее или используют таблицы соответствий.

Итог

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

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

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

Можно ли программно добавить новое значение в перечисление?

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

Чем отличается ПредопределенноеЗначение от обращения через квадратные скобки?

Оба способа принимают имя строкой, но ведут себя по-разному при ошибке: ПредопределенноеЗначение возвращает Неопределено, а обращение Перечисления.Имя["НесуществующееИмя"] вызывает исключение. Для разбора внешних данных безопаснее первый вариант, для жёсткого контроля — второй.

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

Ссылка на перечисление — отдельный тип, не строка. При сравнении со строкой результат всегда ложь, а в запросе такое условие может вообще не вернуть данных. Сравнивайте ссылку со ссылкой, а строку предварительно преобразуйте через ПредопределенноеЗначение.

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

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

Что вернёт запрос, если в параметр передать пустую ссылку перечисления?

Запрос корректно отберёт записи, где реквизит не заполнен, то есть равен пустой ссылке. Это штатный способ найти документы и элементы с незаполненным реквизитом типа перечисление.

Работает ли ЗНАЧЕНИЕ() в запросе для перечислений из расширения?

Да, если расширение подключено и значение добавлено в заимствованное перечисление, функция ЗНАЧЕНИЕ(Перечисление.Имя.НовоеЗначение) разрешится корректно. Без подключённого расширения тот же запрос выдаст ошибку, поэтому такие запросы не стоит размещать в общем коде основной конфигурации.