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