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

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

В процессе разработки на платформе 1С:Предприятие 8.3 (особенно при работе с управляемыми формами) программисты часто сталкиваются с задачей фильтрации строк в табличной части или таблице значений прямо на экране пользователя. Стандартный и наиболее очевидный инструмент для этого — свойство элемента формы ОтборСтрок. Однако при попытке реализовать отбор по нескольким значениям одной и той же колонки (например, показать строки, где тип документа равен "1" ИЛИ "5") разработчики упираются в жесткие ограничения платформы.

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

В чем заключается ограничение свойства ОтборСтрок?

Свойство управляемой формы ОтборСтрок принимает исключительно объект типа ФиксированнаяСтруктура. Этот механизм спроектирован разработчиками платформы только для условий строгого равенства и логического "И" между различными колонками.

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


// Этот код вызовет ошибку платформы!
МассивДок = Новый Массив;
МассивДок.Добавить("1");
МассивДок.Добавить("5");

ПараметрыОтбора = Новый Структура("Операция", МассивДок);
Элементы.ТЗ.ОтборСтрок = Новый ФиксированнаяСтруктура(ПараметрыОтбора);

приведет к ошибке "Значение структуры не должно быть коллекцией". Платформа 1С не умеет самостоятельно сопоставлять одиночное значение ячейки в строке с элементами переданной коллекции.

Попытка добавить несколько одинаковых ключей в структуру отбора также не увенчается успехом, поскольку ключи структуры по определению должны быть уникальными:


// Так сделать тоже не получится — ключи структуры продублировать нельзя
Отбор = Новый Структура;
Отбор.Вставить("ВидДоступа", ВидДоступа1);
Отбор.Вставить("ВидДоступа", ВидДоступа2); 

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

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

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

Рассмотрим пошагово, как реализовать этот алгоритм:

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

Посмотрим на пример практической реализации в коде:


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

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

Способ №2. Использование условного оформления формы

Этот способ позволяет решить задачу исключительно декларативным путем на клиенте без обхода строк таблицы в цикле. Платформа 1С предоставляет мощный инструмент — УсловноеОформление формы, которое поддерживает сложные условия, включая вид сравнения "В списке" или "Не в списке".

Разберем пример кода, который скрывает строки, не входящие в массив разрешенных значений:


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

Важное предупреждение: Несмотря на кажущуюся простоту, этот метод имеет серьезный недостаток. При установке свойства Видимость = Ложь через условное оформление в тонком клиенте (и особенно в веб-клиенте) строки физически не схлопываются. На экране пользователя могут отображаться пустые белые строки без текста. Поэтому использовать условное оформление для полного скрытия строк в таблицах не рекомендуется стандартами разработки фирмы "1С".

Способ №3. Буферизация данных (Для таблиц "только для чтения")

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

При изменении фильтров мы просто очищаем отображаемую таблицу и программно копируем в нее нужные строки из источника:


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

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

Резюме: какой метод выбрать?

Проанализировав все варианты, сделаем выводы:

  1. Если пользователю требуется интерактивно редактировать данные (ставить галочки, менять суммы) и при этом скрывать/показывать строки по сложному фильтру — используйте Способ №1 (Вспомогательная колонка видимости). Это золотой стандарт программирования в управляемом интерфейсе 1С.
  2. Если таблица предназначена только для просмотра — используйте Способ №3 (Буферизация данных), так как он обеспечивает максимальное быстродействие интерфейса без лишней нагрузки на отрисовку скрытых элементов.
← На главную