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