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