Как отфильтровать список номенклатуры по вычисляемым полям и остаткам в 1С (Обычные формы)?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При доработке форм списка справочника Номенклатура в конфигурациях на обычных формах (например, «Управление торговлей», редакция 10.3) часто возникает задача: скрыть из списка позиции, у которых отсутствуют остатки на складах или нет данных в вычисляемых колонках. Разберем, как правильно реализовать такую фильтрацию без потери производительности при работе с большим каталогом товаров.

Почему нельзя отфильтровать строки в событиях ПриВыводеСтроки или ПриПолученииДанных

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

  1. Данные уже получены платформами: На момент вызова события платформа 1С уже сформировала список отображаемых строк. Управлять составом или «отказываться» от вывода строки в этих событиях технически невозможно.
  2. Проблема с производительностью: Если выполнять запросы к регистрам остатков внутри события оформления строк, при прокрутке списка система будет совершать десятки цикличных запросов к базе данных, что приведет к критическим зависаниям интерфейса.

Ограничения объекта СправочникСписок

Объект формы СправочникСписок строится на базе динамического считывания данных из БД. Платформенный отбор (через свойство Отбор) поддерживает работу только с теми реквизитами, которые являются индексированными полями самого справочника или его табличных частей. Отфильтровать данные по колонкам, рассчитанным в коде «на лету», стандартным отбором нельзя.

Проанализируем основные архитектурные варианты решения этой задачи.

Вариант 1. Использование индексированного реквизита-признака (Денормализация)

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

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

ЭлементыФормы.СправочникСписок.НастройкаОтбора.ЕстьОстаток.Доступность = Истина;
СправочникСписок.Отбор.ЕстьОстаток.Значение = Истина;
СправочникСписок.Отбор.ЕстьОстаток.Использование = Истина;

В этом случае платформа на уровне SQL-запроса моментально отсечет пустые позиции без нагрузки на интерфейс.

Вариант 2. Наложение отбора по массиву ссылок (ВидСравнения.ВСписке)

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

Сформируем запрос к остаткам номенклатуры и передадим массив отобранных ссылок в параметр отбора:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ТоварыНаСкладахОстатки.Номенклатура КАК Ссылка
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
    |ГДЕ
    |	ТоварыНаСкладахОстатки.КоличествоОстаток > 0";

РезультатЗапроса = Запрос.Выполнить();
СписокСсылок = Новый СписокЗначений;
СписокСсылок.ЗагрузитьЗначения(РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка"));

СправочникСписок.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
СправочникСписок.Отбор.Ссылка.Значение = СписокСсылок;
СправочникСписок.Отбор.Ссылка.Использование = Истина;

Важное замечание: этот метод подходит для небольших и средних объемов данных. Если список ссылок с остатками превысит несколько тысяч позиций, передача огромного массива в условие SQL-запроса IN (...) вызовет задержку при обновлении списка.

Вариант 3. Замена СправочникСписок на Таблицу Значений или Построитель Запроса

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

Рассмотрим порядок действий для реализации собственного динамического вывода:

  1. Разместим на форме элемент управления ТабличноеПоле с типом данных ТаблицаЗначений или используем объект ПостроительЗапроса.
  2. При открытии формы или смене текущей родительской группы выполняем запрос, соединяющий таблицу справочника с виртуальными таблицами остатков и цен.
  3. В секции ГДЕ запроса фильтруем строки по условию наличия ненулевых остатков.
  4. Выгружаем результат запроса в табличное поле.

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

← На главную