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

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

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

Разбор проблемы: почему не срабатывает НачалоВыбора?

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

  1. Кнопка выбора (три точки) — она открывает полноценную форму выбора справочника. Именно на её нажатие реагирует событие НачалоВыбора.
  2. Кнопка выпадающего списка (стрелка вниз) — она открывает быстрый список выбора или историю последних введенных значений. На её нажатие реагирует событие НачалоВыбораИзСписка.

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

Решение 1: Использование режима выбора из списка

Если список доступных элементов невелик и заранее известен, можно перевести поле в режим работы "Combo Box". Для этого в конфигураторе или программно установим свойство РежимВыбораИзСписка в значение Истина. Посмотрим на логику работы в этом режиме: поле перестает открывать стандартную форму справочника и начинает работать исключительно с фиксированным списком.

Рассмотрим пример программного заполнения такого списка:


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

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

Решение 2: Программная установка фиксированных настроек (Фильтры)

Если нам все же нужно открывать форму выбора, но с наложенным фильтром, правильнее всего будет использовать параметр ФиксированныеНастройки. Разберем по шагам, как это реализовать в событии НачалоВыбора, чтобы пользователь видел в форме только нужные элементы.

Проанализируем следующий алгоритм:

  1. Перехватываем событие НачалоВыбора.
  2. Устанавливаем СтандартнаяОбработка = Ложь.
  3. Формируем список разрешенных ссылок на сервере.
  4. Создаем настройки компоновки данных с отбором ВСписке.
  5. Открываем форму выбора с этими настройками.

Пример реализации кода:


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

Решение 3: Параметры выбора в свойствах реквизита

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

Если же фильтр должен меняться динамически, мы можем управлять этим свойством программно. Рассмотрим, как это сделать:


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

Важный нюанс: История выбора при вводе

Проанализируем ситуацию: вы настроили все фильтры, но при нажатии на поле пользователь все равно видит старые, "запрещенные" элементы. Это происходит из-за механизма Истории выбора. Система запоминает, что пользователь выбирал ранее, и предлагает это в первую очередь, игнорируя новые программные фильтры.

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

Когда использовать ОбработкаПолученияДанныхВыбора?

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

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

← На главную