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