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

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

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

Выясним причину поведения динамического списка

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

Кроме того, у самих папок справочника Номенклатура реквизит ТипНоменклатуры, как правило, либо не заполнен вовсе, либо механизм построения дерева выводит их независимо от заданного условия на уровне записей. В результате пользователь видит все дерево каталогов, где большинство папок оказывается пустыми.

Рассмотрим несколько способов устранения этой проблемы в зависимости от бизнес-требований к интерфейсу выбора.

Способ 1. Исключение групп через параметр отбора «ЭтоГруппа = Ложь»

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

Посмотрим на пример программного открытия формы выбора:


ЗначениеОтбора = Новый Структура;
ЗначениеОтбора.Вставить("ТипНоменклатуры", Перечисления.ТипыНоменклатуры.Услуга);
ЗначениеОтбора.Вставить("ЭтоГруппа", Ложь);

ПараметрыФормы = Новый Структура("Отбор", ЗначениеОтбора);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, Элемент);

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

Способ 2. Отключение иерархического просмотра динамического списка

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

Разберем по шагам, как это сделать в обработчике ПриСозданииНаСервере формы выбора:

  1. Проверяем наличие переданных параметров отбора.
  2. Для таблицы формы, связанной с динамическим списком, программно отключаем иерархию, переключив свойство Отображение или управляя иерархическим просмотром динамического списка.
  3. В результате элементы отображаются без родительских узлов, и пустые папки не мешают пользователю.

Способ 3. Отбор по виду сравнения «В списке» с включением родителей

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

Проанализируем алгоритм реализации:

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

Посмотрим на пример кода установки такого отбора:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	Номенклатура.Родитель КАК Родитель
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.ТипНоменклатуры = &ТипНоменклатуры
    |	И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("ТипНоменклатуры", Перечисления.ТипыНоменклатуры.Услуга);

Результат = Запрос.Выполнить().Выгрузить();

СписокСсылок = Новый Массив;
Для Каждого Стр Из Результат Цикл
    СписокСсылок.Добавить(Стр.Ссылка);
    
    ТекущийРодитель = Стр.Родитель;
    Пока ЗначениеЗаполнено(ТекущийРодитель) Цикл
        Если СписокСсылок.Найти(ТекущийРодитель) = Неопределено Тогда
            СписокСсылок.Добавить(ТекущийРодитель);
        КонецЕсли;
        ТекущийРодитель = ТекущийРодитель.Родитель;
    КонецЦикла;
КонецЦикла;

// Передаем массив в параметры формы выбора
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Ссылка", СписокСсылок);
ПараметрыФормы = Новый Структура("Отбор", ПараметрыОтбора);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, Элемент);

Важное ограничение: данный способ отлично подходит для относительно небольших справочников. Если количество номенклатурных позиций исчисляется десятками или сотнями тысяч, передача массивного списка ссылок в параметр запроса динамического списка может вызвать существенное падение производительности СУБД или ошибку переполнения параметров.

Способ 4. Ограничение корня через свойство «РодительВерхнегоУровня»

В конфигурациях, где структура каталога номенклатуры стандартизирована, услуги нередко сгруппированы внутри одного корневого каталога (например, папка «Услуги»). В этом случае нет необходимости рассчитывать списки ссылок или отключать иерархию.

Рассмотрим применение свойства таблицы формы РодительВерхнегоУровня. В обработчике ПриСозданииНаСервере формы выбора достаточно указать ссылку на корневую папку услуг:

Элементы.Список.РодительВерхнегоУровня = КорневаяПапкаУслуг;

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

Способ 5. Доработка запроса динамического списка

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

После вычисления вспомогательного поля (например, ЕстьУслугиВГруппе) на уровне динамического списка настраивается составной отбор:

(ЭтоГруппа = Истина И ЕстьУслугиВГруппе = Истина) ИЛИ (ЭтоГруппа = Ложь И ТипНоменклатуры = &ТипНоменклатуры)

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

← На главную