Как отметить флажками только видимые строки табличной части с учетом отбора в обычных формах 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке различных обработок загрузки, пакетного проведения или корректировки данных мы часто сталкиваемся со стандартной задачей: предоставить пользователю возможность отметить строки флажками («галочками»). Для этого обычно создается кнопка «Отметить все», под которой скрывается простой обход коллекции в цикле:


Для Каждого Стр Из ТабличнаяЧасть Цикл
    Стр.Пометка = Истина;
КонецЦикла;

Однако если пользователь установил в табличном поле отбор (например, отобрал строки по конкретному контрагенту или группе номенклатуры), такой простой цикл проставит флажки абсолютно во всех строках таблицы, включая скрытые фильтром. Выясним причину такого поведения и подробно разберем правильные способы решения этой задачи для обычных форм платформы «1С:Предприятие».

В чем заключается архитектурная особенность обычных форм

Проанализируем ситуацию: почему простой перебор затрагивает скрытые строки? В обычном приложении ТабличноеПоле — это элемент пользовательского интерфейса, отвечающий за визуализацию. Источник его данных (например, ТабличнаяЧасть или ТаблицаЗначений) — это независимая коллекция, хранящаяся в памяти. Когда пользователь накладывает фильтр через стандартное окно отбора, условие применяется только к визуальному отображению строк в элементе формы. Сама исходная таблица никак не фильтруется и не изменяет своего состава. Платформа не предоставляет встроенного метода вроде ПолучитьОтобранныеСтроки(), поэтому нам необходимо программно определить, попадает ли конкретная строка под текущие настройки фильтра.

Способ 1. Использование метода ПроверитьСтроку()

Рассмотрим самый быстрый, наглядный и лаконичный метод, реализованный непосредственно у элемента управления ТабличноеПоле. Метод ПроверитьСтроку() принимает в качестве параметра строку источника данных и возвращает Истина, если строка удовлетворяет условиям отбора, установленным в интерфейсе.

Разберем по шагам, как реализовать этот алгоритм:

  1. Организуем стандартный цикл обхода строк исходной коллекции данных.
  2. Для каждой строки вызываем функцию ЭлементыФормы.ИмяТабличногоПоля.ПроверитьСтроку(Строка).
  3. Если метод возвращает Истина, устанавливаем признак пометки.

Посмотрим на пример программного кода:


Для Каждого Стр Из ТабличнаяЧасть Цикл
    Если ЭлементыФормы.ТабличнаяЧасть.ПроверитьСтроку(Стр) Тогда
        Стр.Пометка = Истина;
    КонецЕсли;
КонецЦикла;

Рассмотрим подробнее важные нюансы этого подхода:

  1. Корректность при отключенном отборе: если пользователь не накладывал никаких условий или флажки в окне отбора сняты, метод ПроверитьСтроку() штатно возвращает Истина для каждой строки, то есть отметятся все позиции.
  2. Поддержка сложных условий: данный метод берет на себя всю сложность логики платформы — он без дополнительных усилий корректно обрабатывает виды сравнения «В иерархии», «В списке», «Содержит», интервалы дат и строковые подстроки.
  3. Производительность: метод вызывается у элемента интерфейса. На небольших и средних таблицах (до нескольких сотен строк) он работает мгновенно. Однако если таблица содержит тысячи строк, постоянное обращение к интерфейсному элементу в цикле может вызывать просадку производительности.

Способ 2. Применение ПостроителяОтчета для больших объемов данных

Если таблица содержит большое количество строк или требуется обработать массив данных с высокой скоростью без прямого опроса элемента управления в цикле, наиболее эффективным решением выступает объект ПостроительОтчета. Важно отметить, что использовать следует именно ПостроительОтчета, а не ПостроительЗапроса, так как он поддерживает прямое подключение коллекций из оперативной памяти через ОписаниеИсточникаДанных.

Разберем реализацию этого механизма по шагам:

  1. Создаем экземпляр объекта ПостроительОтчета.
  2. Передаем нашу таблицу значений или табличную часть в свойство ИсточникДанных с помощью объекта ОписаниеИсточникаДанных.
  3. Переносим активные настройки отбора из табличного поля в отбор построителя отчета.
  4. Выполняем построитель и выгружаем результат в отфильтрованную таблицу значений.
  5. Проставляем признак пометки в исходной таблице только для тех строк, которые вошли в полученный результат.

Посмотрим на пример кода:


Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаДанных);

// Переносим только включенные пользователем условия отбора
Для Каждого ЭлементОтбора Из ЭлементыФормы.ТабличноеПолеДанных.Отбор Цикл
    Если ЭлементОтбора.Использование Тогда
        НовыйОтбор = Построитель.Отбор.Добавить(ЭлементОтбора.Имя);
        НовыйОтбор.ВидСравнения = ЭлементОтбора.ВидСравнения;
        НовыйОтбор.Значение = ЭлементОтбора.Значение;
        НовыйОтбор.Использование = Истина;
    КонецЕсли;
КонецЦикла;

Построитель.Выполнить();
ТаблицаРезультат = Построитель.Результат.Выгрузить();

// Проставляем отметки в исходной таблице
Для Каждого Стр Из ТаблицаДанных Цикл
    Если ТаблицаРезультат.Найти(Стр.НомерСтроки, "НомерСтроки") <> Неопределено Тогда
        Стр.Пометка = Истина;
    КонецЕсли;
КонецЦикла;

Этот способ работает автономно в памяти, изолирован от интерфейсного контекста отрисовки и позволяет быстро обрабатывать значительные массивы записей со сложными критериями отбора.

Ограничения стандартных методов НайтиСтроки() и ВыделенныеСтроки

Проанализируем альтернативные варианты, которые часто упоминаются разработчиками, и выясним, почему они не подходят как универсальное решение:

  1. Метод таблицы НайтиСтроки(): принимает в качестве параметра структуру. Этот метод не подходит для имитации пользовательского отбора, поскольку работает исключительно по точному совпадению значений. Он не умеет работать с условиями «В иерархии», списками значений, сравнениями на больше/меньше и подстроками.
  2. Свойство ВыделенныеСтроки: если пользователь вручную нажмет в таблице комбинацию клавиш Ctrl+A, в коллекцию ВыделенныеСтроки действительно попадут только видимые с учетом отбора элементы. Однако в обычных формах платформа не имеет программного метода для вызова операции «Выделить все», поэтому опираться на это свойство при нажатии отдельной кнопки на панели нельзя.

Рекомендации по оптимизации интерфейса

При массовом изменении флажков в строках табличного поля платформа может инициировать перерисовку элементов и вызывать события интерфейса (например, ПриВыводеСтроки или пересчет итогов). Чтобы процесс выполнения операции происходил максимально быстро и без мерцания формы, применяйте следующие правила:

  1. Прямая работа с данными: изменяйте реквизиты непосредственно у объекта строки коллекции данных, а не через обращение к свойствам текущей строки табличного поля.
  2. Приоритет выбора: для стандартных прикладных списков и документов объемом до нескольких сотен строк используйте метод ПроверитьСтроку() как наиболее компактный и надежный. При работе с объемными таблицами выгрузки предпочтение отдавайте объекту ПостроительОтчета.
← На главную