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