Как в 1С посчитать количество строк в таблице после применения фильтра?

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

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

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


// Этот способ НЕ сработает для отфильтрованных данных
КоличествоВсехСтрок = МояТабличнаяЧасть.Количество(); 
// Вернет общее количество строк, игнорируя фильтр на форме

Давайте рассмотрим несколько работающих методов, которые позволяют получить именно количество видимых (отфильтрованных) строк, в основном для обычных форм.

Решение 1: Перебор строк с методом ПроверитьСтроку()

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

Для этой проверки у объекта ТабличноеПоле существует специальный метод — ПроверитьСтроку(). Он принимает в качестве параметра строку табличной части и возвращает 1 (или Истина), если строка видима, и 0 (или Ложь), если она скрыта фильтром.

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

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

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


Процедура ПосчитатьОтфильтрованныеСтроки()

    // 1. Получаем объект табличного поля на форме
    ТаблПоле = ЭлементыФормы.Товары;
    
    // 2. Инициализируем счетчик
    КоличествоВидимыхСтрок = 0;
    
    // 3. Перебираем все строки в источнике данных (ТабличнаяЧасть "Товары")
    Для Каждого ТекущаяСтрока Из Товары Цикл
    
        // 4. Проверяем, видима ли строка с учетом фильтра, и увеличиваем счетчик
        // Метод ПроверитьСтроку вернет 1, если строка видима, и 0, если нет.
        КоличествоВидимыхСтрок = КоличествоВидимыхСтрок + ТаблПоле.ПроверитьСтроку(ТекущаяСтрока);
        
    КонецЦикла;
    
    Сообщить("Количество строк после применения фильтра: " + КоличествоВидимыхСтрок);

КонецПроцедуры

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


// Альтернативный вариант вызова внутри цикла
КоличествоВидимыхСтрок = КоличествоВидимыхСтрок + ТаблПоле.ПроверитьСтроку(ТекущаяСтрока.ПолучитьИдентификатор());

Плюсы метода:

Минусы метода:

Решение 2: Использование невидимой колонки и итогов

Этот способ более хитрый, но и значительно более производительный, особенно для больших объемов данных. Он основан на встроенном механизме платформы по расчету итогов в подвале таблицы.

Идея следующая:

  1. Добавляем служебную колонку. В конфигураторе, в состав реквизитов табличной части (например, Товары), добавляем новый реквизит, назовем его СчетчикСтрок, тип Число (1, 0).
  2. Заполняем колонку единицами. При программном заполнении нашей табличной части мы должны для каждой строки устанавливать значение этого поля равным 1.
  3. Настраиваем подвал и итоги. В свойствах табличного поля на форме включаем отображение подвала (свойство Подвал = Истина). Затем для колонки СчетчикСтрок в свойстве ПутьКДаннымПодвала указываем, что нужно вычислять Сумму.
  4. Скрываем колонку от пользователя. Чтобы служебная колонка не мешала пользователю, ее можно сделать невидимой. Это можно сделать либо в свойствах колонки на форме, сняв галочку "Видимость", либо программно, в событии ПриВыводеСтроки табличного поля.

Пример кода для скрытия колонки:


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Делаем нашу служебную колонку невидимой
    ОформлениеСтроки.Ячейки.СчетчикСтрок.Видимость = Ложь;
КонецПроцедуры

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


// Получаем значение итога из подвала
КоличествоВидимыхСтрок = ЭлементыФормы.Товары.Итог("СчетчикСтрок");
Сообщить("Количество строк после применения фильтра: " + КоличествоВидимыхСтрок);

Плюсы метода:

Минусы метода:

Решение 3: Использование ПостроителяОтчета

Этот метод можно считать несколько избыточным для такой простой задачи, но он также является рабочим. Он заключается в том, чтобы "скормить" наши данные на форме (уже как ТаблицуЗначений) построителю отчета и запросить у него количество записей.

Стоит отметить, что этот способ подходит, если табличное поле на форме связано с данными типа ТаблицаЗначений или является списком (например, СправочникСписок).


Процедура ПосчитатьЧерезПостроитель()

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

КонецПроцедуры

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

Бонус: Современный подход для управляемых форм

Описанные выше методы в основном актуальны для обычных форм. В управляемых формах для этой задачи есть более элегантное и производительное решение. Оно основано на работе с коллекцией отборов таблицы.

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


// Этот код предназначен для УПРАВЛЯЕМЫХ форм

// Получаем текущую структуру отбора, установленного пользователем в таблице
ОтборТаблицы = Элементы.ИмяВашейТаблицыНаФорме.Отбор.ПолучитьЭлементы();

// Выгружаем данные из источника во временную таблицу, применяя этот отбор
ВременнаяТаблица = Объект.ИмяВашейТабличнойЧасти.Выгрузить(ОтборТаблицы);

// Количество строк во временной таблице и будет искомым значением
КоличествоСтрок = ВременнаяТаблица.Количество();

Сообщить("Количество отфильтрованных строк: " + КоличествоСтрок);

Этот подход является предпочтительным для управляемых форм, так как он использует встроенные механизмы платформы для фильтрации данных на уровне коллекций, что гораздо быстрее ручного перебора. Для готовой организации итогов в подвале табличных частей с учетом отбора на управляемых формах подойдёт набор процедур для расчета итогов табличных частей с отбором.

← На главную