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