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