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