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