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