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

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

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

Анализ проблемы: ограничения стандартного свойства ОтборСтрок

Стандартный механизм фильтрации строк в таблице формы — это свойство Элементы.ИмяТаблицы.ОтборСтрок. Проанализируем его особенности. Данное свойство принимает значение типа ФиксированнаяСтруктура. Это накладывает на разработчика два существенных ограничения:

  1. Только прямое равенство: Мы можем передать в структуру имя поля и конкретное значение. Платформа выполнит поиск только на строгое соответствие. Использовать виды сравнения вроде В списке, Содержит или Больше здесь невозможно.
  2. Логическое "И": Если мы добавим в структуру несколько полей, система отобразит только те строки, которые соответствуют всем условиям одновременно. Реализовать логику "ИЛИ" стандартным ОтборСтрок не получится.

Если ваша задача — показать строки, идентификаторы которых входят в определенный массив, или строки, связанные с внешним значением, нам придется применить обходные пути.

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

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

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

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

Рассмотрим пример кода, который выполняет пометку строк на сервере:


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

После того как данные в таблице обновлены, применим сам отбор на клиенте:


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

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

Способ №2: Программное Условное оформление

Если по каким-то причинам вы не можете изменять структуру метаданных (добавлять реквизиты), можно воспользоваться механизмом Условного оформления формы. Мы можем создать правило, которое будет скрывать строки, не подходящие под условие.

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

Пример программного добавления условия оформления для скрытия строк:


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

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

Проблема итогов и нумерации строк

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

  1. Подвал таблицы (Итоги): Если у вашей таблицы включен подвал с отображением суммы по колонке, имейте в виду — платформа продолжает считать сумму по всем строкам, включая скрытые. Чтобы показать пользователю итог только по отфильтрованным записям, вам придется скрыть стандартный подвал и вывести под таблицей отдельный декоративный реквизит, который вы будете пересчитывать вручную в коде одновременно с обновлением отбора.
  2. Номера строк: Колонка НомерСтроки — это индекс записи в коллекции. Если вы отобразили только 1-ю и 10-ю строки, в таблице они так и будут выведены под номерами 1 и 10. Перенумеровать их динамически "по порядку" (1 и 2) без физического изменения порядка строк в объекте невозможно.

Рекомендации по производительности

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

Во-первых, старайтесь выполнять расчеты на сервере и передавать на клиент только конечный результат.
Во-вторых, если данных очень много (десятки тысяч строк), рассмотрите возможность использования Динамического списка. Хотя динамические списки обычно строятся по таблицам базы данных, их можно настроить на работу с временными таблицами, куда предварительно выгружается содержимое вашей ТЧ. Это даст вам всю мощь СКД (Системы компоновки данных) для отборов, включая сложные иерархические условия и произвольные группировки.

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

← На главную