Как ограничить выбор элемента справочника в выпадающем списке и при вводе по строке в 1С?

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

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

Метод 1. Использование механизма «Параметры выбора» (Декларативный метод)

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

Рассмотрим по шагам, как это настроить:

  1. Найдем нужный реквизит в метаданных (например, реквизит Склад в документе ТребованиеНакладная).
  2. В палитре свойств найдем пункт Параметры выбора.
  3. Нажмем на кнопку выбора (три точки) и добавим новый отбор. Например, выберем поле ПометкаУдаления со значением Ложь или установим фильтр по конкретному Родителю или Коду.

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

Метод 2. Обработка получения данных выбора в модуле менеджера

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

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

Рассмотрим пример кода в модуле менеджера справочника Склады:


Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    // Если нам нужно ограничить выбор только для конкретного документа
    Если Параметры.Свойство("ИмяВызывающейФормы") И Найти(Параметры.ИмяВызывающейФормы, "ТребованиеНакладная") > 0 Тогда
        
        СтандартнаяОбработка = Ложь; // Отключаем стандартный поиск платформы
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |	Склады.Ссылка КАК Ссылка,
            |	Склады.Наименование КАК Наименование
            |ИЗ
            |	Справочник.Склады КАК Склады
            |ГДЕ
            |	Склады.Код <> &ЗапрещенныйКод
            |	И Склады.Наименование ПОДОБНО &ТекстПоиска";
        
        Запрос.УстановитьПараметр("ЗапрещенныйКод", "000000001");
        Запрос.УстановитьПараметр("ТекстПоиска", "%" + Параметры.СтрокаПоиска + "%");
        
        ТаблицаРезультатов = Запрос.Выполнить().Выгрузить();
        
        СписокВыбора = Новый СписокЗначений;
        Для Каждого Строка Из ТаблицаРезультатов Цикл
            СписокВыбора.Добавить(Строка.Ссылка, Строка.Наименование);
        КонецЦикла;
        
        ДанныеВыбора = СписокВыбора;
        
    КонецЕсли;

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

В данном примере мы проанализировали ситуацию, исключили элемент с конкретным кодом и сформировали собственный СписокЗначений, который увидит пользователь в выпадающем меню.

Метод 3. Событие «АвтоПодбор» на форме

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

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


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

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

Здесь функция ПолучитьСписокСкладовДляПодбора должна быть серверной, выполнять запрос к базе данных с учетом ваших фильтров и возвращать СписокЗначений.

Метод 4. Ограничение через свойства элемента формы (Обычные формы)

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


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

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

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

Метод 5. Глобальное отключение ввода по строке

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

Проанализируем шаги:

  1. Откроем свойства справочника в конфигураторе.
  2. Перейдем на закладку Поле ввода.
  3. В свойстве Ввод по строке удалим все поля (Наименование, Код).

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

Метод 6. Контроль на уровне сервера (Безопасность)

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

Поэтому рассмотрим обязательный шаг — проверку в модуле объекта. Выясним, как гарантированно запретить запись документа с неверным складом:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    Если Метаданные().Имя = "ТребованиеНакладная" Тогда
        Если Склад.Код = "000000001" Тогда
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Выбран запрещенный склад! Запись невозможна.";
            Сообщение.Поле = "Склад";
            Сообщение.УстановитьДанные(ЭтотОбъект);
            Сообщение.Сообщить();
            
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Подведение итогов

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

Для обеспечения максимальной надежности всегда дублируйте проверку в модуле объекта в обработчике ПередЗаписью или ОбработкаПроверкиЗаполнения. Такой комплексный подход позволит создать стабильную и защищенную от ошибок систему.

← На главную