Часто перед разработчиком 1С встает задача: ограничить список выбора в поле формы. По умолчанию платформа услужливо предлагает пользователю все элементы справочника, на который ссылается реквизит. Однако для удобства работы требуется показывать только определенные, отфильтрованные значения. Давайте разберем, как правильно управлять этим процессом и почему попытки очистить список выбора при открытии формы не приводят к успеху.
Проанализируем ситуацию, с которой столкнулся автор вопроса. У него был готов код для фильтрации списка, но платформа добавляла к его отфильтрованным данным все остальные записи из справочника. Это стандартное поведение, и чтобы его изменить, нужно дать платформе явную команду не делать этого.
Когда пользователь нажимает на кнопку выбора или выпадающий список у поля ввода, платформа запускает стандартный механизм: она формирует список из всех доступных элементов справочника. Попытки очистить список выбора в обработчиках ПриСозданииНаСервере или ПриОткрытии не работают, потому что эти события срабатывают до момента обращения пользователя к элементу. Платформа просто заново заполнит список в момент клика.
Ключ к решению — перехватить событие выбора и отменить стандартную обработку, полностью взяв формирование списка на себя.
Это самый правильный и универсальный способ. Логика отбора, описанная в модуле менеджера справочника, будет работать везде, где пользователь будет выбирать элементы этого справочника, а не только на одной конкретной форме. Это обеспечивает целостность и предсказуемость поведения системы.
Для этого используется обработчик события ОбработкаПолученияДанныхВыбора.
Рассмотрим по шагам:
Справочник.Номенклатура.МодульМенеджера).ОбработкаПолученияДанныхВыбора.
СтандартнаяОбработка = Ложь;
ДанныеВыбора.Посмотрим на пример. Допустим, нам нужно, чтобы в поле выбора номенклатуры отображались только услуги.
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
// 1. Отменяем стандартное заполнение списка всеми элементами.
// Это самый важный шаг!
СтандартнаяОбработка = Ложь;
// 2. Создаем список значений, который будем возвращать.
ДанныеВыбора = Новый СписокЗначений;
// 3. Формируем запрос для получения только нужных нам данных.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Представление КАК Представление
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа
| И Номенклатура.Услуга = ИСТИНА";
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
// 4. Загружаем результат запроса в наш список выбора.
ДанныеВыбора.ЗагрузитьЗначения(РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка"));
КонецЕсли;
КонецПроцедуры
Часто фильтр зависит от значения другого поля на форме (например, показать договоры только для выбранного контрагента). Напрямую из модуля менеджера получить доступ к реквизитам формы нельзя. Для этого существует специальный механизм — Связи параметров выбора.
Связи параметров выбора у элемента, для которого настраиваете отбор (например, поле "Договор").Параметры в обработчике ОбработкаПолученияДанныхВыбора.Пример использования параметров:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ДанныеВыбора = Новый СписокЗначений;
// Проверяем, был ли передан параметр отбора "Владелец"
Если Параметры.Свойство("Отбор") И ТипЗнч(Параметры.Отбор) = Тип("Структура") И Параметры.Отбор.Свойство("Владелец") Тогда
ВыбранныйКонтрагент = Параметры.Отбор.Владелец;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Владелец", ВыбранныйКонтрагент);
Запрос.Текст =
"ВЫБРАТЬ
| ДоговорыКонтрагентов.Ссылка
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
|ГДЕ
| ДоговорыКонтрагентов.Владелец = &Владелец";
Результат = Запрос.Выполнить().Выгрузить();
ДанныеВыбора.ЗагрузитьЗначения(Результат.ВыгрузитьКолонку("Ссылка"));
КонецЕсли;
КонецПроцедуры
Если логика фильтрации уникальна и нужна только в одной-единственной форме, можно использовать ее собственные события. Основным событием для этого является НачалоВыбора.
Этот обработчик срабатывает непосредственно перед тем, как платформа покажет пользователю список. Здесь мы также можем отменить стандартное поведение и подставить свой список.
Пример для модуля формы:
&НаКлиенте
Процедура НоменклатураНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
// Отменяем стандартное открытие формы выбора и показ всех элементов
СтандартнаяОбработка = Ложь;
// Способ 1: Сформировать список прямо здесь (если данных немного)
СписокДляВыбора = Новый СписокЗначений;
// ... здесь логика заполнения списка ...
// Открываем форму выбора с нашим списком
ВыбранноеЗначение = ВыбратьИзСписка(СписокДляВыбора, Элемент);
Если ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
Элемент.Значение = ВыбранноеЗначение.Значение;
КонецЕсли;
// Способ 2: Вызвать серверную процедуру для формирования списка
// и затем показать его пользователю.
КонецПроцедуры
Этот подход менее предпочтителен, так как логика оказывается "зашита" в конкретную форму и не будет переиспользована в других местах.
Иногда даже после правильной настройки отбора пользователь может видеть "лишние" значения. Часто это не полный список справочника, а история ранее выбранных значений. Чтобы избежать путаницы, рекомендуется для таких полей отключать историю.
В свойствах элемента формы найдите свойство История выбора при вводе и установите значение в "Не использовать".
Таким образом, для управления списком выбора используйте системный обработчик ОбработкаПолученияДанныхВыбора в модуле менеджера и всегда помните про команду СтандартнаяОбработка = Ложь;, которая является ключом к полному контролю над поведением платформы.