При работе с конфигурациями на базе «Обычных форм», такими как «Управление торговлей» редакции 10.3, разработчики часто сталкиваются с тем, что стандартные механизмы отбора ведут себя неочевидно. Одной из классических проблем является попытка скрыть объекты, помеченные на удаление, в форме списка справочника. Если обычные элементы (карточки) скрываются корректно, то группы (папки) продолжают отображаться в списке, даже если они помечены на удаление. Разберем детально, почему это происходит и как мы можем решить эту задачу несколькими способами.
Для начала разберем типичный код, который программисты используют для установки фильтра. Чаще всего это делается в обработчике события ПриОткрытии или ПередОткрытием формы списка:
ЭлементОтбораСписок = Список.Отбор.ПометкаУдаления;
ЭлементОтбораСписок.ВидСравнения = ВидСравнения.Равно;
ЭлементОтбораСписок.Значение = Ложь;
ЭлементОтбораСписок.Использование = Истина;
С точки зрения логики код абсолютно верен. Мы обращаемся к свойству Отбор табличного поля, выбираем поле ПометкаУдаления и устанавливаем жесткий фильтр на значение Ложь. Однако, если в форме включен режим «Иерархический просмотр», мы увидим, что папки, помеченные на удаление, никуда не исчезли.
Выясним причину этого явления. Платформа «1С:Предприятие 8» в режиме иерархии отдает приоритет сохранению структуры дерева данных. Если система скроет папку, в которой содержатся элементы, НЕ помеченные на удаление, то эти элементы «повиснут в воздухе» — пользователю будет непонятно, к какой группе они относятся. Чтобы избежать нарушения логической целостности визуального дерева, движок обычных форм игнорирует отбор по булевым полям для родительских групп, если включена иерархия. Это особенность внутреннего SQL-запроса, который генерирует платформа для построения динамического списка в обычных формах.
Самый быстрый и простой способ заставить отбор работать — это отключить иерархический просмотр. Когда справочник отображается в виде плоского списка, платформа применяет условия отбора ко всем строкам без исключения, будь то элементы или группы.
Рассмотрим, как это реализовать программно. В модуле формы, сразу после установки отбора, добавим следующую строку:
// Отключаем иерархический режим, чтобы отбор сработал для всех типов записей
ЭлементыФормы.СправочникСписок.ИерархическийПросмотр = Ложь;
Важный нюанс: Этот метод подходит только в том случае, если пользователю не критично видеть структуру «папка-элемент». Если же иерархия жизненно необходима для навигации, этот способ нам не подойдет, и придется рассмотреть альтернативы.
Если нам критически важно сохранить иерархию, мы можем попробовать воздействовать на визуальное представление строк. В табличном поле списка есть событие ПриВыводеСтроки. Мы можем прописать логику, которая будет скрывать строку, если объект помечен на удаление.
Разберем пример реализации:
Процедура СправочникСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Если ДанныеСтроки.ПометкаУдаления Тогда
ОформлениеСтроки.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию: этот метод имеет существенный недостаток. Установка свойства Видимость = Ложь в этом событии не удаляет запись из выборки базы данных. В результате в списке могут появляться «пустые» области, некорректно работать полоса прокрутки (скролл), а при навигации клавиатурой фокус может попадать на невидимые строки. Мы не рекомендуем использовать этот метод для полной очистки списка, так как он сильно портит пользовательский интерфейс.
Если стоит задача, чтобы помеченные на удаление объекты вообще никогда не попадали в поле зрения пользователя (и это касается не только одной формы, а всей системы в целом), лучшим решением будет настройка Row Level Security (RLS).
Посмотрим на алгоритм действий:
ГДЕ ПометкаУдаления = ЛОЖЬ
В этом случае платформа на уровне SQL-запроса будет отсекать ненужные записи. Что самое важное — иерархия в списке будет строиться автоматически только из тех папок, которые соответствуют условию. Если папка помечена на удаление, она просто не попадет в выборку, и система перестроит дерево так, как будто этой папки никогда не существовало. Это наиболее «чистое» и производительное решение с точки зрения архитектуры 1С.
Для сравнения рассмотрим, как эта же задача решается в современных редакциях (например, в УТ 11 или БП 3.0), использующих управляемые формы. Там основным инструментом отображения списков является объект ДинамическийСписок.
В управляемых формах нам не нужно бороться с платформой. Мы можем просто изменить текст запроса динамического списка. Разберем по шагам:
Список на форме.
ВЫБРАТЬ
СправочникНоменклатура.Ссылка,
СправочникНоменклатура.Код,
СправочникНоменклатура.Наименование
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ГДЕ
НЕ СправочникНоменклатура.ПометкаУдаления
В динамическом списке 8.3 иерархия строится «на лету» на основании полученных данных. Если запрос не вернул помеченную папку, она не отобразится, а её подчиненные элементы (если они не помечены) будут отображены на уровень выше или согласно настройкам группировки. Это работает гораздо стабильнее и предсказуемее, чем в старых «обычных» формах.
Мы выяснили, что стандартный отбор в обычных формах при включенной иерархии — это «узкое место» платформы. Чтобы решить проблему в «Управлении торговлей 10.3», мы рекомендуем:
ПриВыводеСтроки для скрытия объектов, так как это создает визуальные артефакты.Помните, что скрытие папки, в которой есть «живые» элементы, всегда создает риск того, что пользователь потеряет эти элементы в структуре справочника. Поэтому перед внедрением таких фильтров всегда уточняйте у бизнес-заказчика, как именно должны отображаться сиротские записи (элементы без видимого родителя).