Как сделать отбор строк в таблице на управляемой форме по условию сравнения суммы?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах 1С разработчики часто сталкиваются с задачей быстрой фильтрации строк в табличной части документа, обработке или реквизите формы типа ТаблицаЗначений. Стандартное свойство элемента управления ОтборСтрок отлично справляется с простыми задачами, когда требуется отобрать строки по конкретному совпадению, например по номенклатуре. Однако при попытке отфильтровать строки по условию вида Сумма > 5000 возникает сложность.

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

Почему стандартный ОтборСтрок не работает с операторами сравнения

Проанализируем принцип работы свойства ОтборСтрок. Данное свойство элемента формы «Таблица» принимает исключительно значение типа ФиксированнаяСтруктура (или Неопределено для сброса фильтра). Механизм платформы сопоставляет значения ключей этой структуры со значениями в колонках таблицы строго по принципу точного равенства. Платформа 1С не поддерживает в данном свойстве операторы больше, меньше, вхождение в список или отрицание.

Также важно отметить частое заблуждение относительно «Условного оформления». С помощью условного оформления формы нельзя физически скрыть или свернуть строку коллекции данных — свойство Видимость там управляет только ячейками или колонками целиком. Метод НайтиСтроки() у таблиц значений также ограничен точным соответствием значений по структуре.

Способ 1. Использование служебной булевой колонки для отбора

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

Разберем по шагам, как правильно реализовать этот подход:

  1. Добавим в табличную часть или в коллекцию строк реквизит ПолеОтбора (или ПодходитПодУсловие) с типом Булево. Если показывать этот флаг пользователю не требуется, снимем видимость соответствующей колонки на форме.
  2. Обойдем строки таблицы в цикле и проставим булев флаг в зависимости от выполнения нашего условия по сумме.
  3. Применим стандартный ОтборСтрок по значению Истина.

Посмотрим на пример кода клиентской процедуры, управляющей видимостью строк:


&НаКлиенте
Процедура ПрименитьОтборПоСумме(Элемент)
    
    // Пересчитываем признак соответствия условию для всех строк коллекции
    Для Каждого СтрокаТЧ Из Объект.Номенклатура Цикл
        СтрокаТЧ.ПолеОтбора = (СтрокаТЧ.Сумма > 5000);
    КонецЦикла;
    
    // Устанавливаем или сбрасываем отбор строк таблицы
    Если ФильтрПоСуммеВключен Тогда
        Элементы.Номенклатура.ОтборСтрок = Новый ФиксированнаяСтруктура("ПолеОтбора", Истина);
    Иначе
        Элементы.Номенклатура.ОтборСтрок = Неопределено;
    КонецЕсли;
    
КонецПроцедуры

Обратим внимание на важную деталь: если пользователь продолжает редактировать суммы непосредственно в таблице при включенном фильтре, флаг для текущей строки необходимо обновлять в событии ПриИзменении поля Сумма, иначе фильтрация станет неактуальной.


&НаКлиенте
Процедура НоменклатураСуммаПриИзменении(Элемент)
    
    ТекущаяСтрока = Элементы.Номенклатура.ТекущиеДанные;
    Если ТекущаяСтрока <> Неопределено Тогда
        ТекущаяСтрока.ПолеОтбора = (ТекущаяСтрока.Сумма > 5000);
    КонецЕсли;
    
КонецПроцедуры

Способ 2. Фильтрация через Компоновщик настроек (для динамических списков)

Выясним причину частой путаницы среди разработчиков: если таблица отображает данные из базы данных (например, записи регистра или список документов), в качестве источника данных используется ДинамическийСписок, а не табличная часть. У динамического списка свойства ОтборСтрок нет вовсе — отборы в нем настраиваются через компоновщик настроек.

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

Посмотрим, как программно добавить условие сравнения сумм в ДинамическийСписок:


&НаСервере
Процедура УстановитьОтборДинамическогоСписка(СуммаОтсечения)
    
    ОтборСписка = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
    ОтборСписка.Элементы.Очистить();
    
    Если СуммаОтсечения > 0 Тогда
        ЭлементОтбора = ОтборСписка.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Сумма");
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
        ЭлементОтбора.ПравоеЗначение = СуммаОтсечения;
        ЭлементОтбора.Использование = Истина;
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Разделение данных на скрытое хранилище и отображаемую таблицу

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

  1. Реквизит формы (например, скрытая ТаблицаЗначений), где хранятся все исходные данные.
  2. Отображаемая коллекция данных формы, привязанная к таблице в интерфейсе.

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

← На главную