Как реализовать отбор по вложенным группам в форме выбора 1С?

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

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

Проблема стандартного отбора по родителю

Когда мы используем простую структуру отбора через параметры формы, например Отбор.Вставить("Родитель", ГруппаСкладов), платформа применяет строгое равенство. Это означает, что в список попадут только те элементы, у которых в поле Родитель записана именно эта группа. Если внутри этой группы есть другая папка «Склады филиалов», элементы внутри неё отображены не будут. Выясним причину: для работы с иерархией необходимо использовать вид сравнения ВИерархии, который недоступен через простую структуру Отбор в параметрах открытия формы.

Решение через фиксированные настройки компоновки данных

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

Проанализируем пример кода для открытия формы выбора справочника Склады с отбором по иерархии:


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

В данном примере мы используем параметр ФиксированныеНастройки. Важно понимать, что такие настройки пользователь не сможет изменить или отключить в самой форме выбора, что гарантирует соблюдение бизнес-логики.

Отображение данных: Список против Дерева

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

Почему не срабатывает событие ПриИзменении?

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

В нашем примере мы передаем Элемент (само поле ввода) в качестве третьего параметра. Это сообщает системе, что результат выбора должен быть возвращен именно в это поле. В этом случае 1С самостоятельно заполнит реквизит и инициирует событие ПриИзменении. Если же вам требуется выполнить сложную логику после выбора, лучше использовать ОписаниеОповещения.

Проблема ввода по строке

Даже если форма выбора настроена идеально, остается проблема «ввода по строке». Если пользователь начнет печатать название склада прямо в поле, система по умолчанию проигнорирует наши настройки из НачалоВыбора и предложит варианты из всего справочника. Чтобы ограничить выбор и здесь, существует два основных пути:

  1. Свойства элемента формы: В конфигураторе для поля ввода можно настроить свойство СвязиПараметровВыбора или ПараметрыВыбора. Однако они плохо поддерживают иерархию.
  2. Модуль менеджера: Использование обработчика ОбработкаПолученияДанныхВыбора. Рассмотрим этот метод как самый надежный.

В модуле менеджера справочника Склады мы можем перехватить запрос на подбор данных:


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

Подведение итогов

Для реализации полноценного отбора по вложенным группам необходимо комбинировать несколько подходов. Во-первых, использовать ФиксированныеНастройки с видом сравнения ВИерархии для формы выбора. Во-вторых, переключать режим отображения списка в Список для удобства поиска. В-третьих, не забывать про обработку ввода по строке в модуле менеджера, чтобы исключить возможность выбора недопустимых элементов без открытия формы.

Такой комплексный подход гарантирует стабильную работу интерфейса и чистоту данных в вашей базе 1С.

← На главную