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