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

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

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

Почему стандартный ОтборСтрок не работает со списком значений

Проанализируем архитектурное ограничение платформы «1С:Предприятие 8». Свойство элемента формы ОтборСтрок предназначено для быстрой фильтрации данных таблицы, но принимает исключительно объект ФиксированнаяСтруктура. Это накладывает строгое системное ограничение: платформа проверяет только точное совпадение (оператор «Равно»).

Такие привычные операторы сравнения, как «В списке», «В иерархии», «Не равно», диапазоны или сложные логические условия ИЛИ/И, через свойство ОтборСтрок для табличных частей объектов не поддерживаются. Если мы передадим структуру вида Новый ФиксированнаяСтруктура("Номенклатура", СписокНоменклатуры), платформа будет искать строку, ячейка которой буквально равна объекту СписокЗначений, а не сопоставлять вхождение элемента в этот список.

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

Рассмотрим рабочие способы обхода этого ограничения.

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

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

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

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

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


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

Теперь рассмотрим клиентский код применения и сброса фильтрации:


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

&НаКлиенте
Процедура СброситьОтбор(Команда)
    
    // Для отключения отбора достаточно присвоить Неопределено
    Элементы.Продукция.ОтборСтрок = Неопределено;
    
КонецПроцедуры

Способ 2. Отображение через вспомогательный реквизит формы «ТаблицаЗначений»

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

  1. В редакторе формы создаем реквизит формы с типом ТаблицаЗначений, повторяющий колонки исходной табличной части, и добавляем служебную колонку ПодходитПоОтбору.
  2. Элемент формы «Таблица» связываем с созданным реквизитом формы, а не с Объект.Продукция.
  3. При открытии формы загружаем данные из Объект.Продукция в созданную таблицу формы.
  4. К этой таблице формы точно так же применяется свойство ОтборСтрок по булевой колонке.
  5. В обработчике формы ПередЗаписьюНаСервере выгружаем данные обратно в реальную табличную часть документа через Объект.Продукция.Загрузить(...).

Этот способ позволяет не трогать метаданные, однако требует внимательности при синхронизации данных, чтобы не потерять внесенные пользователем правки при записи объекта.

Способ 3. Буферизация и физическая фильтрация строк

Если отбор носит сугубо прикладной характер и требуется лишь на короткое время, можно применить буферизацию:

  1. При активации отбора полная табличная часть выгружается во временное хранилище или скрытый реквизит формы.
  2. В основной табличной части Объект.Продукция физически удаляются строки, не подходящие под список значений.
  3. При отключении фильтра или перед непосредственной записью документа исходный массив строк восстанавливается из буфера.

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

Способ 4. Динамический список (только для режима просмотра)

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

  1. В качестве источника данных динамического списка настраивается запрос к табличной части документа из информационной базы с отбором по ссылке текущего документа: ГДЕ ДокументТабличнаяЧасть.Ссылка = &ТекущийДокумент.
  2. В динамическом списке платформенный механизм компоновки данных поддерживает любые операции сравнения: ВидСравненияКомпоновкиДанных.ВСписке, ВидСравненияКомпоновкиДанных.ВИерархии и другие.

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

← На главную