Как ограничить список доступных значений перечисления в реквизите формы 1С

Программист IT и автоматизация бизнеса
← На главную

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

Метод 1. Динамическое формирование списка через событие НачалоВыбора

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

Разберем по шагам реализацию этого метода в коде. Нам потребуется обработчик события на клиенте:


&НаКлиенте
Процедура ХозяйственнаяОперацияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Останавливаем стандартный вывод всех значений перечисления
    СтандартнаяОбработка = Ложь;    
    
    // Создаем новый список значений, который будет содержать только нужные элементы
    СписокВыбораОпераций = Новый СписокЗначений;
    
    // Добавляем разрешенные значения, используя метод ПредопределенноеЗначение
    СписокВыбораОпераций.Добавить(ПредопределенноеЗначение("Перечисление.цкпХозяйственныеОперацииКонтроляКачества.ВнутрипроизводственныйКонтроль"));
    СписокВыбораОпераций.Добавить(ПредопределенноеЗначение("Перечисление.цкпХозяйственныеОперацииКонтроляКачества.ВходнойКонтроль"));
    СписокВыбораОпераций.Добавить(ПредопределенноеЗначение("Перечисление.цкпХозяйственныеОперацииКонтроляКачества.ВыходнойКонтроль"));
    СписокВыбораОпераций.Добавить(ПредопределенноеЗначение("Перечисление.цкпХозяйственныеОперацииКонтроляКачества.ДополнительныйОтбор"));
    СписокВыбораОпераций.Добавить(ПредопределенноеЗначение("Перечисление.цкпХозяйственныеОперацииКонтроляКачества.Переконтроль"));
        
    // Передаем сформированный список в параметр ДанныеВыбора
    ДанныеВыбора = СписокВыбораОпераций;

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

В этом примере мы использовали параметр ДанныеВыбора. Это более современный и правильный подход для события НачалоВыбора, так как он позволяет системе корректно отобразить выпадающее меню. Важно помнить: при использовании СтандартнаяОбработка = Ложь мы полностью берем на себя ответственность за то, что увидит пользователь.

Метод 2. Оптимизация через заполнение списка ПриСозданииНаСервере

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Очищаем стандартный список, если он был заполнен автоматически
    Элементы.ХозяйственнаяОперация.СписокВыбора.Очистить();
    
    // Наполняем список только нужными значениями
    Элементы.ХозяйственнаяОперация.СписокВыбора.Добавить(Перечисления.цкпХозяйственныеОперацииКонтроляКачества.ВнутрипроизводственныйКонтроль);
    Элементы.ХозяйственнаяОперация.СписокВыбора.Добавить(Перечисления.цкпХозяйственныеОперацииКонтроляКачества.ВходнойКонтроль);
    
    // Устанавливаем режим выбора из списка, чтобы пользователь не мог ввести произвольный текст
    Элементы.ХозяйственнаяОперация.РежимВыбораИзСписка = Истина;

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

При таком подходе нам не нужно прописывать код в НачалоВыбора. Система сама будет подставлять этот список при нажатии на кнопку выбора. Свойство РежимВыбораИзСписка делает элемент похожим на обычное комбо-бокс (выпадающий список), что часто удобнее для перечислений.

Метод 3. Глобальное ограничение через Модуль Менеджера

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

Для этого нам необходимо перейти в Модуль менеджера соответствующего перечисления и создать там обработчик ОбработкаПолученияДанныхВыбора. Рассмотрим, как это выглядит:


Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    // Если нам нужно ограничить выбор везде, кроме специальных случаев
    СтандартнаяОбработка = Ложь;
    
    Список = Новый СписокЗначений;
    Для Каждого ЗначениеИзМетаданных Из Метаданные.Перечисления.цкпХозяйственныеОперацииКонтроляКачества.ЗначенияПеречисления Цикл
        // Допустим, мы скрываем значение с именем "СлужебнаяОперация"
        Если ЗначениеИзМетаданных.Имя <> "СлужебнаяОперация" Тогда
            ИмяЗначения = ЗначениеИзМетаданных.Имя;
            Список.Добавить(Перечисления.цкпХозяйственныеОперацииКонтроляКачества[ИмяЗначения]);
        КонецЕсли;
    КонецЦикла;
    
    ДанныеВыбора = Список;
    
КонецПроцедуры

Этот метод является наиболее архитектурно "чистым", так как логика фильтрации инкапсулирована внутри самого объекта. Однако будьте осторожны: это изменение затронет все формы, где используется данный тип данных.

Важные нюансы и обработка исключений

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

  1. Отображение существующих данных. Если в базе данных уже есть документ, в котором выбрано то самое "скрытое" значение, то при открытии формы пользователь может увидеть пустое поле или системное представление. Чтобы этого избежать, в коде заполнения списка (например, в ПриСозданииНаСервере) нужно проверить: если текущее значение реквизита является "скрытым", его нужно временно добавить в СписокВыбора именно для этого сеанса работы, чтобы пользователь видел актуальные данные.
  2. Автоподбор при вводе текста. Если пользователь начнет вводить название скрытого значения вручную, стандартный механизм 1С может его "подсказать". Чтобы этого не случилось, используйте событие АвтоПодбор на элементе формы, ограничивая в нем ДанныеВыбора аналогично методу 1.
  3. Работа в расширениях. Если ваша конфигурация находится на поддержке, крайне рекомендуется не вносить изменения напрямую (не "снимать с замочка"), а использовать Расширения конфигурации. Вы можете создать расширение, добавить туда форму и использовать аннотацию &После("ПриСозданииНаСервере") для настройки списка выбора. Это значительно упростит последующее обновление программы.
  4. Функциональные опции. Если необходимость скрытия значений зависит от настроек системы (например, включена или выключена какая-то опция в константах), обязательно проверяйте ПолучитьФункциональнуюОпцию() перед формированием списка.

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

← На главную