В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача ограничить видимость строк в табличной части (ТЧ) документа или справочника по определенным критериям. В отличие от динамических списков, где реализована мощная система компоновки данных, табличные части имеют более скромный функционал для фильтрации. Рассмотрим подробно, как обойти стандартные ограничения и реализовать гибкий отбор строк.
Самый простой и быстрый способ отфильтровать данные — использовать свойство элемента формы ОтборСтрок. Оно позволяет установить фильтр, который будет работать на уровне платформы. Однако у этого метода есть существенное ограничение: он принимает только объект типа ФиксированнаяСтруктура. Это означает, что мы можем реализовать только условие «Равно» и только логическое «И» между полями.
Разберем пример, когда нам нужно отобрать строки по одному конкретному значению. Проанализируем программный код:
// Пример простого отбора по одному полю
&НаКлиенте
Процедура УстановитьПростойОтбор()
Отбор = Новый Структура();
Отбор.Вставить("Отдел", Объект.НужныйОтдел);
// Преобразование в ФиксированнуюСтруктуру обязательно
Элементы.Выплаты.ОтборСтрок = Новый ФиксированнаяСтруктура(Отбор);
КонецПроцедуры
Если нам необходимо установить отбор сразу по нескольким полям (например, по отделу и по статусу активности), мы должны передать их в структуру через запятую. Рассмотрим ситуацию из обсуждения, где требуется отобрать «Просроченные» и «Уцененные» товары одновременно:
// Отбор по нескольким реквизитам (Условие И)
Элементы.Товары.ОтборСтрок = Новый ФиксированнаяСтруктура("Просроченный, Уцененный", Истина, Истина);
Важный нюанс: Попытка передать в значение структуры массив (например, список отделов) не сработает. Система будет искать совпадение значения в ячейке с самим объектом «Массив», что технически невозможно в рамках типовых типов данных ТЧ. Если вам нужен отбор по типу «В списке» или условие «ИЛИ», стандартный ОтборСтрок не подойдет.
Когда стандартных средств недостаточно, мы используем проверенный временем метод «служебного реквизита». Суть заключается в том, чтобы создать колонку, которая не хранится в базе данных, но помогает управлять видимостью строк. Выясним, как это реализовать по шагам.
Объект, разверните нужную табличную часть и добавьте новый реквизит (например, МаркерВидимости) с типом Булево. Обратите внимание, что этот реквизит должен быть именно реквизитом формы, чтобы не раздувать структуру таблиц в базе данных.Видимость = Ложь, так как пользователю эта техническая колонка не нужна.Истина там, где условия выполняются.Проанализируем пример кода для реализации сложного условия (например, если нам нужно показать товары, которые либо «Просрочены», либо принадлежат к определенному списку отделов):
&НаКлиенте
Процедура ПрименитьСложныйОтбор()
// Проходим по всем строкам табличной части
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
// Здесь можно прописать любое сложное условие (И, ИЛИ, В Списке)
УсловиеВыполнено = (СтрокаТЧ.Просроченный = Истина)
ИЛИ (МассивНужныхОтделов.Найти(СтрокаТЧ.Отдел) <> Неопределено);
СтрокаТЧ.МаркерВидимости = УсловиеВыполнено;
КонецЦикла;
// Устанавливаем простой отбор по нашей служебной колонке
Элементы.Товары.ОтборСтрок = Новый ФиксированнаяСтруктура("МаркерВидимости", Истина);
КонецПроцедуры
Этот метод позволяет реализовать абсолютно любую логику фильтрации. Главный минус — производительность на очень больших таблицах (десятки тысяч строк), так как обход коллекции на клиенте может занять время. В таких случаях рекомендуется выполнять расчет признака видимости на сервере.
Еще один вариант, который часто обсуждается на форумах — это использование механизма УсловноеОформление. Мы можем задать правило, при котором строки, не подходящие под условие, будут иметь свойство Видимость = Ложь.
Рассмотрим, как это сделать программно:
&НаСервере
Процедура НастроитьУсловноеОформление()
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// Условие: если поле Просрочен = Ложь, то скрываем строку
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Просроченный");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Ложь;
// Настройка оформления
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Видимость", Ложь);
// Применяем ко всей строке таблицы
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Товары");
КонецПроцедуры
Важное предостережение: У этого метода есть неприятные визуальные эффекты. Во-первых, строки физически остаются в памяти и влияют на расчет итогов в подвале таблицы (если они включены). Во-вторых, при прокрутке скрытых строк может «прыгать» полоса прокрутки или возникать пустые области до тех пор, пока пользователь не кликнет мышкой в область таблицы. Поэтому метод со служебной колонкой считается более профессиональным и надежным.
При использовании метода со служебной колонкой вы можете столкнуться с тем, что форма документа становится «модифицированной» (появляется звездочка в заголовке), хотя пользователь ничего не менял, а просто применил фильтр. Чтобы этого избежать, убедитесь, что ваш служебный реквизит добавлен именно в состав Реквизитов Формы, а не в метаданные объекта. Изменение реквизитов формы не вызывает срабатывания флага модифицированности, что позволяет пользователю закрыть форму без лишних вопросов о сохранении, если он просто просматривал данные.
Частая ошибка начинающих разработчиков (как видно из сообщения 7 и 9 в обсуждении) — попытка использовать программный код динамического списка для обычной таблицы. Поле Отбор доступно для объекта ДинамическийСписок, но отсутствует у типа ДанныеФормыКоллекция (которым является табличная часть на управляемой форме). Для ТЧ всегда используйте либо ОтборСтрок, либо манипуляции с видимостью через служебные поля.
Подведем итог: если вам нужно простое равенство — используйте ФиксированнаяСтруктура. Если нужно условие «ИЛИ» или «В списке» — внедряйте невидимую булеву колонку-маркер и фильтруйте по ней. Это обеспечит стабильную работу интерфейса и корректное отображение данных для пользователя.