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