Как установить отбор строк в табличной части по нескольким колонкам?

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

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

Разбор механизма ОтборСтрок

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

Важная особенность: свойство ОтборСтрок работает по принципу «полной замены». Если мы сначала установим отбор по складу, а следующей строкой кода — по номенклатуре, то первый отбор будет полностью заменен вторым. Чтобы отбор работал одновременно по двум и более полям, их необходимо передать в систему единовременно внутри одной структуры.

Реализация множественного отбора по шагам

Рассмотрим ситуацию, когда у нас есть три фильтра на форме: Группа складов, Склад и Номенклатура. Нам нужно, чтобы табличная часть отображала только те строки, которые соответствуют всем заполненным фильтрам одновременно.

Выясним правильный алгоритм действий:

  1. Создаем обычную (изменяемую) Структура.
  2. Проверяем каждое значение фильтра на заполненность.
  3. Если значение заполнено, добавляем его в структуру.
  4. Преобразуем готовую структуру в ФиксированнаяСтруктура.
  5. Присваиваем результат свойству ОтборСтрок.

Рассмотрим пример кода, реализующий этот подход:


&НаКлиенте
Процедура УстановитьФильтрТаблицы()

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

КонецПроцедуры

Проблема использования значения Неопределено

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

Запомните: чтобы отключить фильтрацию по конкретной колонке, ключ этой колонки должен просто отсутствовать в структуре отбора. Именно поэтому мы используем метод Вставить() только внутри условия Если ЗначениеЗаполнено().

Логика объединения условий

Важно понимать, что штатный механизм ОтборСтрок всегда объединяет условия по правилу «И». Это значит, что если вы указали Склад «А» и Товар «Б», система покажет только те строки, где одновременно указан и этот склад, и этот товар.

Если же ваша задача требует реализации логики «ИЛИ» (например, показать все товары со Склада «А» ИЛИ все товары с видом «Услуга»), стандартный ОтборСтрок не справится. В этом случае проанализируем обходной путь:

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

Пример реализации такого «велосипеда» (если стандартный механизм не подходит):


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

&НаКлиенте
Процедура ПрименитьСложныйОтбор()
    ОбновитьВидимостьСтрокНаСервере();
    
    // Устанавливаем отбор по одной служебной колонке
    Структура = Новый Структура("ВыбратьСтроку", Истина);
    Элементы.Настройка.ОтборСтрок = Новый ФиксированнаяСтруктура(Структура);
КонецПроцедуры

Особенности работы в Веб-клиенте

Проанализируем ситуацию с работой в браузерах. Иногда разработчики замечают, что в тонком клиенте отбор по нескольким колонкам работает корректно, а в веб-клиенте игнорируются все условия, кроме первого. Это может быть связано с особенностями конкретных релизов платформы 1С. Если вы столкнулись с такой проблемой, рекомендуется убедиться, что вы используете актуальную версию платформы (не ниже 8.3.15). В качестве временного решения для веб-клиента можно использовать метод с дополнительной булевой колонкой, описанный выше, так как он гарантирует стабильный результат независимо от окружения.

Производительность и ограничения

Посмотрим на вопрос производительности. Механизм ОтборСтрок выполняется на стороне клиента. Если в вашей табличной части находятся тысячи строк, установка фильтра может вызвать кратковременное зависание интерфейса. В таких случаях эффективнее использовать Динамический список с настроенным отбором, так как он фильтрует данные на уровне SQL-запроса, передавая на клиент только нужные строки.

Также стоит помнить, что ОтборСтрок поддерживает только строгое равенство. Вы не сможете реализовать через него поиск по подстроке (например, «найти все товары, в названии которых есть слово "коробка"») или отбор «больше/меньше» для числовых полей. Для таких задач используйте механизмы Условного оформления (скрытие строк) или упомянутый выше метод с булевой колонкой.

Сброс всех отборов

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

Элементы.ИмяВашейТаблицы.ОтборСтрок = Неопределено;

Это действие мгновенно снимает все ограничения и очищает память клиента от параметров фильтрации.

← На главную