Разработка и Конфигурация · 8 мин
Как перебрать все значения перечисления в 1С
Способы перебора значений перечисления в 1С: цикл по Перечисления.Метаданные, ПеречислениеМенеджер, запросы. Примеры кода, ошибки и ответы на вопросы.
Перечисление в 1С — это прикладной объект с фиксированным списком значений, заданным в конфигураторе. В отличие от справочника, состав значений перечисления нельзя изменить в режиме предприятия, поэтому перебор его элементов выполняется не запросом к данным, а через метаданные или менеджер перечисления. Это принципиальная разница, которую часто упускают начинающие разработчики.
Задача перебрать все значения перечисления возникает при формировании отчётов, заполнении списков выбора, проверке полноты данных и при выгрузке во внешние системы. В зависимости от контекста — толстый клиент, тонкий клиент, внешнее соединение — доступны разные подходы.
Ниже разобраны основные способы: цикл через метаданные, обращение через менеджер перечисления, перебор в запросе и перебор без знания имени перечисления на этапе разработки. Для каждого приведён рабочий код и указаны ограничения.
Перебор значений через метаданные
Универсальный способ — обратиться к коллекции ЗначенияПеречисления объекта метаданных. Каждый элемент этой коллекции хранит имя значения, синоним и индекс. Само значение перечисления получают по имени через менеджер.
Для Каждого ЗначениеМетаданных Из Метаданные.Перечисления.СтавкиНДС.ЗначенияПеречисления Цикл
ЗначениеПеречисления = Перечисления.СтавкиНДС[ЗначениеМетаданных.Имя];
Сообщить(ЗначениеМетаданных.Имя + " — " + Строка(ЗначениеПеречисления));
КонецЦикла;
Такой код работает и на сервере, и на клиенте (в управляемых формах — в контексте &НаСервере или &НаКлиенте, поскольку перечисления доступны в обоих). Порядок перебора соответствует порядку значений, заданному в конфигураторе, что удобно для вывода в привычной последовательности.
Если нужен только синоним (представление, которое видит пользователь), его можно взять напрямую из метаданных без получения значения: ЗначениеМетаданных.Синоним. Это быстрее и не требует обращения к менеджеру.
Перебор через менеджер перечисления
Менеджер перечисления Перечисления.ИмяПеречисления позволяет обращаться к значениям по имени как к свойству или через квадратные скобки. Обращение через квадратные скобки со строковым именем — ключевой приём для универсального кода, где имя значения заранее неизвестно.
Менеджер = Перечисления.СтавкиНДС;
Для Каждого ЗначениеМетаданных Из Менеджер.Метаданные().ЗначенияПеречисления Цикл
ТекущееЗначение = Менеджер[ЗначениеМетаданных.Имя];
// работа с ТекущееЗначение
КонецЦикла;
Дополнительно у менеджера есть методы ПолучитьИндексПоИмени и обратное получение имени по значению через метаданные: ЗначениеМетаданных = Перечисления.СтавкиНДС.Ставка20.Метаданные() вернёт объект описания конкретного значения, откуда доступны имя и синоним.
Обратное преобразование — получить имя по значению — делается так: ИмяЗначения = ЗначениеПеречисления.Метаданные().Имя не сработает, так как метод вернёт метаданные всего перечисления. Правильно: перебрать коллекцию значений и сравнить, либо использовать Метаданные.Перечисления.Имя.ЗначенияПеречисления.Найти(Индекс).
Универсальный перебор без знания имени перечисления
Когда имя перечисления приходит как строка (например, из настроек обработки), используют индексацию по коллекции Метаданные.Перечисления и Перечисления:
ИмяПеречисления = "СтавкиНДС";
Для Каждого ЗначениеМетаданных Из Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления Цикл
Значение = Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];
Сообщить(Строка(Значение));
КонецЦикла;
Перед обращением стоит проверить существование объекта: Метаданные.Перечисления.Найти(ИмяПеречисления) вернёт Неопределено, если перечисления с таким именем нет. Без проверки попытка обращения вызовет исключение и прервёт выполнение обработки.
Перебор значений в запросе
В языке запросов перебрать значения перечисления можно двумя способами. Первый — виртуальная таблица Перечисление.ИмяПеречисления, которая содержит колонки Ссылка и Порядок:
ВЫБРАТЬ
Ставки.Ссылка КАК Ставка,
Ставки.Порядок КАК Порядок
ИЗ
Перечисление.СтавкиНДС КАК Ставки
УПОРЯДОЧИТЬ ПО
Ставки.Порядок
Второй способ — явное перечисление значений через ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.Ставка20). Этот вариант подходит, когда нужны не все значения, а конкретные, например для фильтрации данных документов.
Виртуальная таблица перечисления удобна для отчётов на СКД: она позволяет вывести все значения, включая те, по которым нет данных, и соединить их с оборотами. Это стандартный приём для отчётов вида «показать нули по отсутствующим позициям».
Запрос = Новый Запрос("ВЫБРАТЬ Т.Ссылка ИЗ Перечисление.СтавкиНДС КАК Т"); Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл Сообщить(Выборка.Ссылка); КонецЦикла;Заполнение списка выбора и проверка результата
Частая практическая задача — заполнить список выбора элемента формы всеми значениями перечисления. На управляемой форме это делается на сервере:
Элементы.ПолеСтавки.СписокВыбора.Очистить();
Для Каждого ЗначениеМетаданных Из Метаданные.Перечисления.СтавкиНДС.ЗначенияПеречисления Цикл
Элементы.ПолеСтавки.СписокВыбора.Добавить(
Перечисления.СтавкиНДС[ЗначениеМетаданных.Имя],
ЗначениеМетаданных.Синоним);
КонецЦикла;
После реализации проверьте результат: количество элементов в списке должно совпадать с числом значений в конфигураторе, порядок — с порядком в палитре свойств перечисления, представления — с синонимами. Если список пуст, чаще всего причина в том, что код выполнился не в том контексте или имя перечисления указано с ошибкой.
Как проверить результат
Совпадает с числом значений в конфигураторе
Меньше — проверьте имя перечисления и контекст выполнения
Соответствует порядку в метаданных
Произвольный — возможно, использована сортировка в запросе без Порядок
Выводятся синонимы, понятные пользователю
Выводятся технические имена — используйте свойство Синоним
Типичные ошибки при переборе перечислений
Самая распространённая ошибка — попытка перебрать перечисление как справочник через Выбрать(). У менеджера перечисления нет такого метода, потому что значения не хранятся в базе данных как объекты. Вторая частая ошибка — обращение к значению по синониму вместо имени: Перечисления.СтавкиНДС["НДС 20%"] вызовет исключение, нужно использовать имя Ставка20.
Также разработчики забывают, что при переименовании значения в конфигураторе весь код со строковыми обращениями к старому имени перестаёт работать. Поэтому строковые имена стоит выносить в константы модуля или минимизировать их использование.
Часто задаваемые вопросы
Как получить имя значения перечисления по самому значению?
Используйте индекс: Индекс = Перечисления.ИмяПеречисления.Индекс(Значение), затем Метаданные.Перечисления.ИмяПеречисления.ЗначенияПеречисления[Индекс].Имя. Прямого свойства «Имя» у значения перечисления нет.
Можно ли перебрать перечисления на клиенте в управляемом приложении?
Да, перечисления и их метаданные доступны и в контексте &НаКлиенте. Обращение к Метаданные на клиенте работает, но при большом числе обращений логичнее выполнить перебор один раз на сервере и передать готовый список.
Как перебрать значения всех перечислений конфигурации сразу?
Вложенным циклом: сначала Для Каждого ПеречислениеМетаданные Из Метаданные.Перечисления, затем внутри цикл по ПеречислениеМетаданные.ЗначенияПеречисления. Значение получают через Перечисления[ПеречислениеМетаданные.Имя][ИмяЗначения].
Почему запрос к таблице Перечисление.Имя возвращает мало колонок?
Виртуальная таблица перечисления содержит только Ссылка и Порядок — это ограничение платформы. Синоним в запросе получают через ПРЕДСТАВЛЕНИЕ(Ссылка), а имя значения в запросе недоступно.
Как сравнить значение реквизита с конкретным значением перечисления?
Напрямую: Если Документ.Ставка = Перечисления.СтавкиНДС.Ставка20 Тогда. В запросе используйте ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.Ставка20) в условии ГДЕ.
Что важно запомнить
Перебор значений перечисления выполняется через коллекцию ЗначенияПеречисления метаданных, а само значение получают по имени через менеджер. В запросах используйте виртуальную таблицу Перечисление.Имя. Пустая ссылка в перебор не входит, а строковые имена требуют проверки на существование.