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