Как программно установить отбор по коду группы и иерархии при открытии формы выбора 1С

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

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

Анализ проблемы: почему стандартные свойства не подходят

Рассмотрим ситуацию: у нас есть иерархический справочник Детали и группа Радиодетали с конкретным кодом. Если мы попытаемся в конфигураторе в свойстве "Параметры выбора" указать Отбор.Код("ММ-000341"), система отработает буквально: она найдет и покажет только один объект — саму группу с этим кодом. Все вложенные в нее элементы (дочерние детали) отображаться не будут, так как их код отличается от указанного.

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

Решение 1: Программное открытие формы с простым отбором по Родителю

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

Проанализируем пример кода для события НачалоВыбора элемента формы:


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

&НаСервереБезКонтекста
Функция ПолучитьСсылкуНаГруппуПоКоду(Знач КодГруппы)
    Возврат Справочники.Детали.НайтиПоКоду(КодГруппы);
КонецФункции

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

Решение 2: Установка отбора "В иерархии" через ФиксированныеНастройки

Если группа содержит в себе другие подгруппы, и вам нужно отобразить всё дерево элементов внутри, простой отбор по родителю не поможет (он покажет только прямых "детей"). В этом случае необходимо использовать механизм компоновки данных динамического списка. Рассмотрим подробнее, как передать условие "В иерархии".

Для реализации глубокого иерархического отбора при открытии формы используется параметр ФиксированныеНастройки. Это объект типа НастройкиКомпоновкиДанных, который платформа накладывает на динамический список формы выбора "сверху", не позволяя пользователю их изменить.


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

Проанализируем ситуацию: использование поля Ссылка в сочетании с видом сравнения ВИерархии позволяет включить в список саму выбранную группу и абсолютно все объекты, находящиеся внутри неё на любом уровне вложенности. Это самый надежный способ реализации подобных задач.

Решение 3: Использование инструментов БСП

Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), как, например, "1С:Бухгалтерия 3.0", вы можете сократить объем кода, используя общие модули. В БСП есть удобные методы для работы с отборами динамических списков.

Например, в модуле ОбщегоНазначенияКлиентСервер существует процедура УстановитьЭлементОтбораДинамическогоСписка. Однако, она чаще применяется уже внутри самой формы выбора (в событии ПриСозданииНаСервере). Если вы создаете свою форму выбора, вы можете передать в неё произвольный параметр (например, ТолькоРадиодетали = Истина) и обработать его внутри формы выбора следующим образом:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("ТолькоРадиодетали") И Параметры.ТолькоРадиодетали Тогда
        
        ГруппаСсылка = Справочники.Детали.НайтиПоКоду("ММ-000341");
        
        // Используем метод БСП для установки отбора
        ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
            Список, 
            "Ссылка", 
            ГруппаСсылка, 
            ВидСравненияКомпоновкиДанных.ВИерархии
        );
        
    КонецЕсли;
    
КонецПроцедуры

Важные рекомендации по оптимизации

При реализации отборов по коду необходимо учитывать следующие моменты:

  1. Предопределенные элементы: Если группа Радиодетали создана в конфигураторе как предопределенная, вам не нужно искать её по коду. Используйте прямое обращение: Справочники.Детали.Радиодетали. Это работает быстрее и исключает ошибки, если пользователь изменит код в режиме "1С:Предприятие".
  2. Кэширование поиска: Функция НайтиПоКоду обращается к базе данных. Если форма выбора открывается часто, имеет смысл вынести поиск ссылки в функцию модуля с повторным использованием значений.
  3. Режим выбора групп и элементов: Если вы хотите, чтобы пользователь мог выбирать только конечные "детали", но не сами группы, добавьте в параметры формы параметр ВыборГруппИЭлементов со значением ИспользованиеГруппИЭлементов.Элементы.
  4. Производительность: Отбор ВИерархии может замедлять работу на огромных справочниках (десятки тысяч элементов). Убедитесь, что поле Родитель индексировано (в типовых справочниках это обычно так и есть).

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

← На главную