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

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

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

Разбираем, какой тип данных имеют перечисления в 1С: хранение в базе, тип значения, сравнение, запросы и типичные ошибки разработчиков при работе с enums.

Перечисление в 1С — это объект метаданных, значения которого задаются на этапе конфигурирования и не могут быть изменены пользователем в режиме предприятия. С точки зрения встроенного языка значение перечисления имеет специальный тип ПеречислениеСсылка.<ИмяПеречисления>, например ПеречислениеСсылка.СтавкиНДС. Это ссылочный тип, а не строка и не число, хотя внешне значение выглядит как предопределённое слово.

Путаница возникает потому, что в запросах, при сериализации и при хранении в базе данных перечисление ведёт себя по-разному: в запросе его можно сравнить со строковым литералом через специальный синтаксис, в XML оно выглядит как строка, а в таблицах СУБД хранится как внутреннее представление. Понимание этих слоёв помогает избежать ошибок сравнения, обмена данными и проектирования реквизитов.

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

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

Во встроенном языке 1С каждое значение перечисления принадлежит типу ПеречислениеСсылка.<Имя>. Проверить это можно функцией ТипЗнч() и сравнить с ожидаемым типом через Тип(). Например, для конфигурации с перечислением «СтавкиНДС» выражение ТипЗнч(Перечисления.СтавкиНДС.НДС20) вернёт тип «ПеречислениеСсылка.СтавкиНДС».

Важно отличать объект метаданных от значения. Менеджер перечисления Перечисления.СтавкиНДС — это объект типа «ПеречислениеМенеджер», а конкретное значение Перечисления.СтавкиНДС.НДС20 — уже ссылка. Путать их нельзя: менеджер используется для получения значений и пустой ссылки, ссылка — для хранения в реквизитах и сравнений.

Тип перечисления строго фиксирован. Если реквизит документа объявлен как ПеречислениеСсылка.СтавкиНДС, присвоить ему значение другого перечисления или строку не получится — платформа выдаст ошибку несоответствия типов. Исключение составляют составные типы, где разработчик явно перечисляет допустимые типы реквизита.

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

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

Порядок значений в списке перечисления имеет значение для сортировки. При упорядочивании в запросе значения перечисления сортируются по порядку следования в конфигураторе, а не по алфавиту. Это удобно для статусов («Черновик → Согласован → Утверждён»), но требует осознанного расположения элементов.

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

Сравнение значений и проверка типа

Сравнение значений перечисления выполняется оператором равенства напрямую: Если Док.Ставка = Перечисления.СтавкиНДС.НДС20 Тогда .... Сравнивать со строкой «НДС20» нельзя — результат будет ложным, потому что типы разные. Это одна из самых частых ошибок начинающих разработчиков.

Для проверки типа переменной используйте связку ТипЗнч() и Тип():

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

// работаем как с перечислением

КонецЕсли;

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

Типичные ошибки
01
Сравнение значения перечисления со строкой — условие никогда не выполняется, логика молча не работает
02
Использование Строка() для сравнения — представление зависит от синонима и может меняться при доработках
03
Присвоение реквизиту значения другого перечисления через составной тип без проверки — ошибка приведения типов в момент записи
04
Удаление значения перечисления без поиска ссылок — битые данные и ошибки обновления базы

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

В языке запросов значение перечисления задаётся литералом вида ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20). Это полноценное ссылочное значение, с ним работают сравнение, соединения и группировки. Передавать значение можно и через параметр: &Ставка, где параметр имеет тип ПеречислениеСсылка.

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

Функция ПРЕДСТАВЛЕНИЕ() в запросе вернёт строковое представление значения, но использовать её для сравнения — плохая практика: представление берётся из синонима и может быть изменено без изменения кода.

bsl
ВЫБРАТЬ
	Продажи.СтавкаНДС КАК Ставка,
	СУММА(Продажи.Сумма) КАК Сумма
ИЗ
	РегистрНакопления.Продажи КАК Продажи
ГДЕ
	Продажи.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20)
СГРУППИРОВАТЬ ПО
	Продажи.СтавкаНДС

Перечисления при обмене и сериализации

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

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

Когда перечисление не подходит: альтернативы

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

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

Сравнение вариантов

Перечисление

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

Справочник

Пользователь сам добавляет элементы. Подходит для открытых списков: контрагенты, номенклатура, склады. В коде обращение по ссылке или поиску.

Предопределённые элементы справочника

Компромисс: часть элементов задана разработчиком и доступна из кода, пользователь может добавлять свои. Требует аккуратности при обмене.

Практические рекомендации и проверка результата

При проектировании реквизита сначала ответьте на вопрос: будет ли пользователь добавлять новые варианты? Если нет и варианты завязаны на ветвления кода — выбирайте перечисление. Располагайте значения в логическом порядке, потому что он определяет сортировку в запросах и списках выбора.

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

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

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

Тип значения в отладчике
Норма

Отображается ПеречислениеСсылка.<Имя>

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

Строка или другой тип — сравнение и запись работать не будут

Сортировка в отчёте
Норма

Значения идут в порядке, заданном в конфигураторе

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

Алфавитный порядок не совпадает с ожидаемым — значения расположены неправильно

Обмен данными
Норма

Значения сопоставляются по именам без ошибок

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

Ошибки разбора или пустые значения после загрузки

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

Перечисление в 1С — это строка или число?

Ни то ни другое. Это ссылочный тип ПеречислениеСсылка.<Имя>. Строковое представление существует только для отображения и сериализации, числового индекса, доступного разработчику, у значения нет.

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

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

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

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

Что произойдёт с данными при переименовании значения перечисления?

Данные в базе не пострадают: реквизиты хранят внутреннюю ссылку, а не имя. Изменится только отображение. Но обмены и внешние интеграции, опирающиеся на имя, могут сломаться.

Чем пустая ссылка перечисления отличается от Неопределено?

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

Может ли один реквизит ссылаться на два разных перечисления?

Да, если в конфигураторе задать составной тип и отметить оба перечисления. В коде тогда потребуется проверка фактического типа значения через ТипЗнч() перед обращением к специфичной логике.

Итог

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

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