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

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

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

Стандартный механизм: Использование свойства ОтборСтрок

Самый простой и быстрый способ отфильтровать данные — использовать свойство элемента формы ОтборСтрок. Оно позволяет установить фильтр, который будет работать на уровне платформы. Однако у этого метода есть существенное ограничение: он принимает только объект типа ФиксированнаяСтруктура. Это означает, что мы можем реализовать только условие «Равно» и только логическое «И» между полями.

Разберем пример, когда нам нужно отобрать строки по одному конкретному значению. Проанализируем программный код:


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

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


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

Важный нюанс: Попытка передать в значение структуры массив (например, список отделов) не сработает. Система будет искать совпадение значения в ячейке с самим объектом «Массив», что технически невозможно в рамках типовых типов данных ТЧ. Если вам нужен отбор по типу «В списке» или условие «ИЛИ», стандартный ОтборСтрок не подойдет.

Метод «Служебной колонки»: Обход ограничений

Когда стандартных средств недостаточно, мы используем проверенный временем метод «служебного реквизита». Суть заключается в том, чтобы создать колонку, которая не хранится в базе данных, но помогает управлять видимостью строк. Выясним, как это реализовать по шагам.

  1. Создание реквизита: В редакторе формы перейдите к реквизиту Объект, разверните нужную табличную часть и добавьте новый реквизит (например, МаркерВидимости) с типом Булево. Обратите внимание, что этот реквизит должен быть именно реквизитом формы, чтобы не раздувать структуру таблиц в базе данных.
  2. Размещение на форме: Перетащите созданный реквизит в элементы таблицы на форме. Установите ему свойство Видимость = Ложь, так как пользователю эта техническая колонка не нужна.
  3. Алгоритм заполнения: При активации отбора нам нужно пройти циклом по всем строкам и установить Истина там, где условия выполняются.

Проанализируем пример кода для реализации сложного условия (например, если нам нужно показать товары, которые либо «Просрочены», либо принадлежат к определенному списку отделов):


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

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

Использование «Условного оформления»

Еще один вариант, который часто обсуждается на форумах — это использование механизма УсловноеОформление. Мы можем задать правило, при котором строки, не подходящие под условие, будут иметь свойство Видимость = Ложь.

Рассмотрим, как это сделать программно:


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

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

Оптимизация: Работа с модифицированностью

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

Почему не работает обращение к «Отбор.Элементы»?

Частая ошибка начинающих разработчиков (как видно из сообщения 7 и 9 в обсуждении) — попытка использовать программный код динамического списка для обычной таблицы. Поле Отбор доступно для объекта ДинамическийСписок, но отсутствует у типа ДанныеФормыКоллекция (которым является табличная часть на управляемой форме). Для ТЧ всегда используйте либо ОтборСтрок, либо манипуляции с видимостью через служебные поля.

Подведем итог: если вам нужно простое равенство — используйте ФиксированнаяСтруктура. Если нужно условие «ИЛИ» или «В списке» — внедряйте невидимую булеву колонку-маркер и фильтруйте по ней. Это обеспечит стабильную работу интерфейса и корректное отображение данных для пользователя.

← На главную