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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Использование события «НачалоВыбора»

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

Проанализируем алгоритм действий: мы отключаем стандартную обработку, создаем свой СписокЗначений, наполняем его нужными элементами и вызываем метод ВыбратьИзСписка. Это позволяет нам полностью контролировать, что увидит пользователь.


&НаКлиенте
Процедура ОбъектНачалоВыбора(Элемент, СтандартнаяОбработка)
    
    // Если мы хотим подавить выбор типа и сразу показать значения:
    СтандартнаяОбработка = Ложь;
    
    СписокЗначений = Новый СписокЗначений;
    // Добавляем только те значения перечисления, которые нам нужны
    СписокЗначений.Добавить(ПредопределенноеЗначение("Перечисление.Статусы.Активен"), "Активный статус");
    СписокЗначений.Добавить(ПредопределенноеЗначение("Перечисление.Статусы.Черновик"), "В работе");
    
    // Показываем список пользователю рядом с элементом формы
    ВыбранноеЗначение = ВыбратьИзСписка(СписокЗначений, Элемент);
    
    // Обрабатываем результат выбора
    Если ВыбранноеЗначение <> Неопределено Тогда
        Объект.ИмяРеквизита = ВыбранноеЗначение.Значение;
    КонецЕсли;
    
КонецПроцедуры

Важный нюанс: при использовании составного типа данных событие НачалоВыбора сработает только после того, как пользователь уже выбрал конкретный тип в стандартном окне (если мы не установили СтандартнаяОбработка = Ложь в самом начале). Если мы хотим ограничить список только когда выбран тип «Перечисление», внутри процедуры нужно проверить текущий тип значения через функцию ТипЗнч.

Способ 2. Реализация через «Режим выбора из списка»

Этот метод часто называют самым «чистым» для визуального восприятия. Мы переводим элемент формы в режим, когда он ведет себя как выпадающий список. Чтобы избежать визуальных багов в составных типах, разработчики часто используют небольшую хитрость: добавляют в составной тип Строку или Число, чтобы платформа не пыталась жестко привязаться к метаданным перечисления.

Разберем реализацию этого метода по шагам (свойства элементов можно также настраивать через редактор форм в режиме предприятия):

  1. Установим свойство элемента формы РежимВыбораИзСписка в значение Истина.
  2. В событии ПриСозданииНаСервере или при изменении условий заполним программно СписокВыбора элемента.
  3. Обязательно очистим список перед заполнением, чтобы избежать дублирования элементов.

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

Выясним причину популярной ошибки «Дубли в списке»: если вы не очистите СписокВыбора, платформа может добавить ваши программные значения к уже существующим стандартным значениям перечисления. Всегда используйте метод Очистить(). Аналогичные подходы применяются, когда требуется доработка динамических списков в сложных формах. Для упрощения работы с кодом и метаданными подойдёт помощник разработчика для написания BSL-кода и проверки синтаксиса.

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

Если вам нужно ограничить список выбора перечисления во всей системе (или во многих формах сразу), наиболее эффективным будет использование механизма ОбработкаПолученияДанныхВыбора в модуле менеджера перечисления. Этот метод также идеально решает проблему «ввода по строке», что особенно важно, когда анализ зависимостей конфигурации показывает широкое использование объекта.

Рассмотрим пример кода в модуле менеджера перечисления (для быстрой генерации подобных конструкций удобно использовать консоль кода с ИИ-помощником (удобно через консоль кода с ИИ-помощником для разработчика 1С)):


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

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

Способ 4. Использование события «НачалоВыбораИзСписка»

Если у элемента формы уже включено свойство КнопкаСпискаВыбора, мы можем использовать специализированное событие СтавкаНДСНачалоВыбораИзСписка (название зависит от вашего реквизита). Проанализируем, как это работает на клиенте и сервере:


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

&НаСервереБезКонтекста
Функция ПолучитьОграниченныйСписокНаСервере()
    
    Список = Новый СписокЗначений;
    Список.Добавить(Перечисления.СтавкиНДС.НДС20, "20%");
    Возврат Список;
    
КонецФункции

Технические нюансы и тонкие настройки

Разберем несколько важных моментов, которые часто упускают при реализации подобных задач:

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

← На главную