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

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

Как получить перечисление на клиенте в 1С

Как получить значение перечисления на клиенте в 1С: предопределённое значение, по имени, с сервера. Примеры кода, ошибки и разбор ограничений управляемых форм.

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

Тем не менее получить значение перечисления на клиенте можно несколькими способами: через функцию ПредопределенноеЗначение(), через вызов серверной процедуры, через кэширование значений при открытии формы или через хранение нужных значений в реквизитах формы. Выбор зависит от того, работаете ли вы в тонком клиенте, веб-клиенте, нужно ли значение один раз или постоянно.

Ниже разобраны рабочие приёмы с примерами кода, типичные ошибки и границы применимости каждого подхода. Материал ориентирован на управляемые формы в режиме «такси», где ограничения клиентского контекста проявляются сильнее всего.

Почему на клиенте нельзя обратиться к менеджеру перечисления напрямую

В управляемом приложении 1С код делится на клиентский и серверный контексты. Менеджеры объектов метаданных — Перечисления, Справочники, Документы — существуют только на сервере, где есть доступ к базе данных. Клиентский контекст работает с уже переданными на него данными: реквизитами формы, значениями, полученными с сервера.

Поэтому конструкция вида Перечисления.СтавкиНДС.НДС20 корректна в серверной процедуре, но в клиентской директиве &НаКлиенте вызовет ошибку. Компилятор модуля формы в зависимости от настроек либо сразу сообщит о недоступности объекта, либо ошибка возникнет при выполнении.

Важно понимать, что само значение перечисления, уже полученное на клиент, — обычный объект типа ПеречислениеСсылка. С ним можно сравнивать, присваивать реквизитам, передавать в процедуры. Ограничение касается только способа получения значения, а не работы с ним.

Способ 1: ПредопределенноеЗначение() — основной метод

Функция ПредопределенноеЗначение() доступна и на клиенте, и на сервере. Она принимает строку с полным путём к значению и возвращает ссылку на перечисление:

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

ВидОперации = ПредопределенноеЗначение("Перечисление.ВидыОпераций.Продажа");

Строка строится по шаблону: Перечисление.ИмяПеречисления.ИмяЗначения. Имена берутся из конфигуратора — это имена, заданные разработчиком в метаданных, а не синонимы (представления), которые видит пользователь. Если в конфигураторе значение называется НДС20, а синоним у него «НДС 20%», в строку подставляется именно НДС20.

Если имя указано неверно, функция возвращает Неопределено, а не ошибку. Это частый источник скрытых дефектов: код выполняется, но сравнение с Неопределено всегда даёт ложь, и ветка логики молча не срабатывает. Поэтому после получения значения полезно проверять результат, особенно при динамическом формировании имени.

bsl
Ставка = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС20");
Если Ставка = Неопределено Тогда
    ВызватьИсключение "Значение перечисления не найдено";
КонецЕсли;

Способ 2: Получение значения с сервера

Когда ПредопределенноеЗначение() недостаточно — например, нужно получить список всех значений перечисления или значение определяется сложной серверной логикой — используют вызов серверной процедуры. В модуле формы создают процедуру с директивой &НаСервере или обращаются к серверному общему модулю.

&НаСервереБезКонтекста

Функция ПолучитьСтавкуНДСПоУмолчанию()

Возврат Перечисления.СтавкиНДС.НДС20;

КонецФункции

&НаКлиенте

Процедура ПриОткрытии(Отказ)

ТекущаяСтавка = ПолучитьСтавкуНДСПоУмолчанию();

КонецПроцедуры

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

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

Способ 3: Кэширование значений при открытии формы

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

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

ВидОперацииПродажа = Перечисления.ВидыОпераций.Продажа;

ВидОперацииВозврат = Перечисления.ВидыОпераций.Возврат;

КонецПроцедуры

Реквизиты формы с типом ПеречислениеСсылка добавляются через панель реквизитов в редакторе формы. После этого в клиентских обработчиках значения доступны напрямую без серверных вызовов и без строковых имён:

&НаКлиенте

Процедура ВидОперацииПриИзменении(Элемент)

Если Объект.ВидОперации = ВидОперацииВозврат Тогда

Элементы.ДокументОснование.Видимость = Истина;

КонецЕсли;

КонецПроцедуры

Порядок настройки кэширования
  1. 1
    Добавьте реквизиты формы с типом ПеречислениеСсылка для каждого нужного значения
  2. 2
    В ПриСозданииНаСервере присвойте реквизитам значения через менеджер перечисления
  3. 3
    Используйте реквизиты в клиентских обработчиках без серверных вызовов
  4. 4
    Проверьте работу формы в тонком и веб-клиенте

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

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

&НаСервереБезКонтекста

Функция СписокСтавокНДС()

Список = Новый СписокЗначений;

Для Каждого Значение Из Метаданные.Перечисления.СтавкиНДС.ЗначенияПеречисления Цикл

Список.Добавить(

Перечисления.СтавкиНДС[Значение.Имя],

Значение.Синоним);

КонецЦикла;

Возврат Список;

КонецФункции

Тип СписокЗначений сериализуется и корректно передаётся между сервером и клиентом, поэтому его можно использовать для заполнения выпадающих списков, параметров выбора и динамических фильтров. Альтернатива — вернуть массив структур с полями «Значение» и «Представление», если нужен более гибкий формат.

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

Сравнение способов

ПредопределенноеЗначение

Быстро, без серверного вызова. Подходит для фиксированных значений. Не возвращает список и представления

Серверный вызов

Универсально, доступны метаданные и любая логика. Минус — сетевой вызов, нельзя злоупотреблять

Кэш в реквизитах формы

Оптимально при многократном использовании в форме. Требует добавления реквизитов и кода в ПриСозданииНаСервере

Типичные ошибки и как их избежать

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

Вторая группа ошибок связана с переименованием значений в конфигураторе. Строковые обращения не отслеживаются механизмом поиска ссылок на объекты метаданных: переименовали значение — строка в коде устарела молча. Снизить риск помогает централизация: вынесите все строковые имена перечислений в один общий модуль с функциями-обёртками.

Третья ошибка — попытка использовать Вычислить() или Выполнить() для обхода ограничения клиентского контекста. Это не сработает: менеджер перечислений физически отсутствует в клиентском окружении, и динамическое выполнение кода это не изменит.

Типичные ошибки
01
Синоним вместо имени в ПредопределенноеЗначение — функция вернёт Неопределено без ошибки
02
Серверный вызов внутри цикла или обработчика ПриИзменении — форма начинает тормозить
03
Отсутствие проверки на Неопределено после получения значения — логика молча не срабатывает
04
Попытка обойти ограничение через Выполнить() — менеджер перечислений недоступен на клиенте в любом случае
05
Прямое обращение Перечисления.Имя.Значение в &НаКлиенте — ошибка компиляции или выполнения

Проверка результата и отладка

После получения значения убедитесь, что оно корректно. Минимальная проверка — сравнение с Неопределено. Более строгая — проверка типа через ТипЗнч() или сравнение с пустой ссылкой, если значение пришло из реквизита объекта:

Если Ставка = Неопределено Тогда

// имя значения указано неверно

ИначеЕсли Не ЗначениеЗаполнено(Ставка) Тогда

// реквизит не заполнен

КонецЕсли;

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

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

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

Результат ПредопределенноеЗначение
Норма

Ссылка нужного типа, сравнение с ожидаемым значением даёт Истина

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

Неопределено — ошибка в строке имени

Значение в табло отладчика
Норма

Отображается тип ПеречислениеСсылка и представление

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

Пустая ссылка или другой тип

Поведение формы
Норма

Ветки логики срабатывают, элементы управляются корректно

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

Условия всегда ложны — значение не совпадает с ожидаемым

FAQ

Можно ли на клиенте обратиться к менеджеру Перечисления напрямую?

Нет. В клиентском контексте управляемой формы менеджеры объектов метаданных недоступны. Используйте ПредопределенноеЗначение() или получите значение серверным вызовом.

Что вернёт ПредопределенноеЗначение, если имя указано с ошибкой?

Функция вернёт Неопределено без генерации ошибки. Поэтому после вызова с динамически формируемым именем всегда проверяйте результат, иначе дефект останется незамеченным.

Как получить представление (синоним) значения перечисления на клиенте?

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

Работает ли ПредопределенноеЗначение в веб-клиенте?

Да, функция доступна в тонком клиенте, веб-клиенте и толстом клиенте управляемого приложения. Это делает её предпочтительным способом для кросс-платформенного клиентского кода.

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

Сформируйте СписокЗначений на сервере (перебором значений через метаданные или менеджер), верните его на клиент и присвойте свойству СписокВыбора элемента формы. СписокЗначений корректно передаётся между контекстами.

Что делать, если значение перечисления нужно в десятках мест формы?

Получите его один раз в ПриСозданииНаСервере и сохраните в реквизит формы типа ПеречислениеСсылка. Все клиентские обработчики будут использовать сохранённое значение без повторных серверных вызовов.

Итог

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

На клиенте перечисление получают через ПредопределенноеЗначение() с точным именем из конфигуратора. Для списков значений и сложной логики — серверный вызов. При многократном использовании значения кэшируют в реквизитах формы. Всегда проверяйте результат на Неопределено.