Как программно установить отбор в форме выбора справочника и скрыть пустые папки

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

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

Метод 1: Использование фиксированных настроек компоновки данных

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

Сначала подготовим массив или список значений на сервере, а затем сформируем настройки для открытия формы. Разберем программный код:


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

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

Проблема «призрачных» папок в иерархических списках

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

Первый и самый простой вариант — принудительно переключить режим просмотра в «Список». Это уберет иерархию вовсе, и все найденные элементы будут выведены сплошным перечнем. Для этого в параметры открытия формы можно добавить:

ПараметрыФормы.Вставить("Отображение", "Список");

Однако если бизнес-задача требует сохранения структуры папок, но скрытия пустых ветвей, нам потребуется более сложный подход.

Метод 2: Скрытие пустых групп через условное оформление

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

Рассмотрим реализацию этого метода. Предположим, мы передаем в форму параметр ГруппаОтбора:


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

Важный нюанс: Условное оформление Видимость = Ложь в динамических списках работает специфично. Оно может не удалять строку полностью, а просто делать ее пустой или скрывать текст. Для полной фильтрации «лишних» веток иерархии на уровне СУБД лучше всего изменять сам текст запроса динамического списка.

Метод 3: Изменение текста запроса динамического списка

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

  1. В форме выбора справочника установим флаг Произвольный запрос.
  2. В событии ПриСозданииНаСервере модифицируем текст запроса, добавляя в него условие ГДЕ.

Пример кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("ТолькоАктивныеСтатьи") Тогда
        ТекстЗапроса = Список.ТекстЗапроса;
        // Добавляем условие прямо в SQL-запрос списка
        ТекстЗапроса = ТекстЗапроса + " ГДЕ СправочникСтатьиБюджета.Статус = &Статус";
        Список.ТекстЗапроса = ТекстЗапроса;
        Список.Параметры.УстановитьЗначениеПараметра("Статус", Перечисления.Статусы.Активен);
    КонецЕсли;
    
КонецПроцедуры

Использование этого метода позволяет полностью исключить ненужные записи из выборки, что положительно сказывается и на производительности, и на корректности отображения иерархии.

Рекомендации по выбору способа

Подведем итоги и выберем оптимальный путь для вашей задачи:

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

← На главную