Как реализовать отбор строк в таблице значений на управляемых формах с условиями «больше» или «меньше»?

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

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

Причина ограничения: почему стандартный метод не работает

Рассмотрим стандартный подход, который работает только для равенства. Когда мы пишем код Элементы.Таблица.ОтборСтрок = Новый ФиксированнаяСтруктура("Сумма", 100);, система ищет строки, где значение в колонке Сумма равно точно 100. Мы не можем передать в структуру объект ВидСравнения или использовать операторы сравнения. Чтобы реализовать условие «Больше» или «Меньше», нам придется использовать обходные пути.

Способ 1: Использование вспомогательной колонки (рекомендуемый метод)

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

Разберем реализацию этого метода по шагам:

  1. Добавление реквизита: В редакторе формы найдем нашу таблицу (реквизит типа ТаблицаЗначений) и добавим в неё новую колонку, например, с именем ПодходитПодФильтр (тип Булево). Добавлять этот реквизит на саму форму (в дерево элементов) не обязательно, он должен существовать только в данных.
  2. Алгоритм расчета: Создадим процедуру, которая будет перебирать строки таблицы и устанавливать значение этого флага в зависимости от нашего условия.
  3. Наложение отбора: Применим стандартный ОтборСтрок по нашей новой колонке.

Проанализируем пример кода для реализации этого подхода:


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

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

Способ 2: Использование Условного оформления (скрытие строк)

Иногда программисты пытаются использовать УсловноеОформление для управления видимостью строк. Рассмотрим подробнее, как это реализовать программно, и выясним причину, по которой этот метод не всегда подходит.

Посмотрим на пример настройки условного оформления для скрытия строк, где значение меньше заданного:


ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ЭлементОформления.Использование = Истина;

// Устанавливаем свойство "Видимость" в Ложь для строк, не подходящих под условие
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Видимость", Ложь);

// Настраиваем условие: Цена < 30
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Цена");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
ЭлементУсловия.ПравоеЗначение = 30;

// Указываем, какие поля нужно скрыть (все колонки таблицы)
Для Каждого Колонка Из Элементы.Товары.ПодчиненныеЭлементы Цикл
    ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
    ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных(Колонка.Имя);
КонецЦикла;

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

Способ 3: Фильтрация через запрос (для больших объемов данных)

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

  1. Выгружаем ТаблицуЗначений из реквизита формы в обычную ТаблицуЗначений на сервере.
  2. Передаем её в запрос как параметр.
  3. В тексте запроса используем секцию ГДЕ для фильтрации по условию Больше, Меньше или МЕЖДУ.
  4. Загружаем результат запроса обратно в реквизит формы.

Проанализируем пример кода:


&НаСервере
Процедура ПрименитьФильтрЗапросом(ПорогСуммы)
    
    ТЗ = Объект.ИтоговаяТаблица.Выгрузить();
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ ИЗ &ТЗ КАК ТЗ;
    |ВЫБРАТЬ * ИЗ ВТ ГДЕ Сумма >= &ПорогСуммы";
    
    Запрос.УстановитьПараметр("ТЗ", ТЗ);
    Запрос.УстановитьПараметр("ПорогСуммы", ПорогСуммы);
    
    Объект.ИтоговаяТаблица.Загрузить(Запрос.Выполнить().Выгрузить());
    
КонецПроцедуры

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

Способ 4: Паттерн «Эталонная и Отображаемая таблицы»

Если данные в таблице не редактируются пользователем напрямую, а служат только для просмотра, удобно использовать две таблицы в реквизитах формы:

При каждом изменении условий фильтра мы очищаем ОтображаемыеДанные и заполняем их из ПолныеДанные методом НайтиСтроки() (если условия на равенство) или простым перебором (для условий больше/меньше). Это гарантирует, что исходные данные всегда под рукой и нам не нужно обращаться к базе данных для повторного получения информации.

Итоги и рекомендации

Мы выяснили, что прямого способа использовать ВидСравнения.Больше в свойстве ОтборСтрок управляемой формы не существует. Однако, комбинируя программный перебор и флаг-индикатор, можно добиться того же результата. Для большинства задач оптимальным выбором будет Способ №1 (Вспомогательная колонка), так как он сохраняет целостность данных в таблице и корректно работает с интерфейсом платформы 8.3.

← На главную