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