В процессе разработки на платформе 1С часто возникает задача: получить точное количество строк в таблице на форме после того, как пользователь применил к ней стандартный или произвольный фильтр (отбор). На первый взгляд, решение кажется очевидным, но стандартный метод подсчета строк не учитывает визуальные фильтры. Разберем эту ситуацию и рассмотрим несколько эффективных способов решения этой задачи.
Основная проблема заключается в том, что отбор применяется к элементу формы (ТабличноеПоле), а данные хранятся в объекте данных (ТабличнаяЧасть или ТаблицаЗначений). Если мы обратимся к свойству Количество() самого объекта данных, мы получим общее число строк, а не количество отфильтрованных.
// Этот способ НЕ сработает для отфильтрованных данных
КоличествоВсехСтрок = МояТабличнаяЧасть.Количество();
// Вернет общее количество строк, игнорируя фильтр на форме
Давайте рассмотрим несколько работающих методов, которые позволяют получить именно количество видимых (отфильтрованных) строк, в основном для обычных форм.
Этот метод является наиболее прямым и логичным для обычных форм. Его суть заключается в том, чтобы программно перебрать все строки в источнике данных и для каждой строки проверить, проходит ли она условия отбора, установленные в табличном поле на форме.
Для этой проверки у объекта ТабличноеПоле существует специальный метод — ПроверитьСтроку(). Он принимает в качестве параметра строку табличной части и возвращает 1 (или Истина), если строка видима, и 0 (или Ложь), если она скрыта фильтром.
Рассмотрим по шагам, как это реализовать:
ТабличнаяЧасть), а к их визуальному представлению (ТабличноеПоле). Обычно это делается через коллекцию ЭлементыФормы.ПроверитьСтроку() для текущей строки и прибавляем результат к нашему счетчику.Посмотрим на пример кода. Предположим, у нас есть табличная часть Товары и связанное с ней табличное поле на форме с таким же именем.
Процедура ПосчитатьОтфильтрованныеСтроки()
// 1. Получаем объект табличного поля на форме
ТаблПоле = ЭлементыФормы.Товары;
// 2. Инициализируем счетчик
КоличествоВидимыхСтрок = 0;
// 3. Перебираем все строки в источнике данных (ТабличнаяЧасть "Товары")
Для Каждого ТекущаяСтрока Из Товары Цикл
// 4. Проверяем, видима ли строка с учетом фильтра, и увеличиваем счетчик
// Метод ПроверитьСтроку вернет 1, если строка видима, и 0, если нет.
КоличествоВидимыхСтрок = КоличествоВидимыхСтрок + ТаблПоле.ПроверитьСтроку(ТекущаяСтрока);
КонецЦикла;
Сообщить("Количество строк после применения фильтра: " + КоличествоВидимыхСтрок);
КонецПроцедуры
Важное уточнение: в некоторых случаях, в зависимости от контекста и версии платформы, может потребоваться передавать в метод не саму строку, а ее идентификатор. Это более универсальный подход.
// Альтернативный вариант вызова внутри цикла
КоличествоВидимыхСтрок = КоличествоВидимыхСтрок + ТаблПоле.ПроверитьСтроку(ТекущаяСтрока.ПолучитьИдентификатор());
Плюсы метода:
Минусы метода:
Этот способ более хитрый, но и значительно более производительный, особенно для больших объемов данных. Он основан на встроенном механизме платформы по расчету итогов в подвале таблицы.
Идея следующая:
Товары), добавляем новый реквизит, назовем его СчетчикСтрок, тип Число (1, 0).Подвал = Истина). Затем для колонки СчетчикСтрок в свойстве ПутьКДаннымПодвала указываем, что нужно вычислять Сумму.ПриВыводеСтроки табличного поля.Пример кода для скрытия колонки:
Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
// Делаем нашу служебную колонку невидимой
ОформлениеСтроки.Ячейки.СчетчикСтрок.Видимость = Ложь;
КонецПроцедуры
В результате платформа будет автоматически рассчитывать сумму по колонке СчетчикСтрок, но только для видимых (отфильтрованных) строк. Таким образом, в подвале таблицы всегда будет отображаться актуальное количество отфильтрованных строк. Получить это значение программно можно, обратившись к итогу по колонке:
// Получаем значение итога из подвала
КоличествоВидимыхСтрок = ЭлементыФормы.Товары.Итог("СчетчикСтрок");
Сообщить("Количество строк после применения фильтра: " + КоличествоВидимыхСтрок);
Плюсы метода:
Минусы метода:
Этот метод можно считать несколько избыточным для такой простой задачи, но он также является рабочим. Он заключается в том, чтобы "скормить" наши данные на форме (уже как ТаблицуЗначений) построителю отчета и запросить у него количество записей.
Стоит отметить, что этот способ подходит, если табличное поле на форме связано с данными типа ТаблицаЗначений или является списком (например, СправочникСписок).
Процедура ПосчитатьЧерезПостроитель()
// Создаем новый объект ПостроителяОтчета
Построитель = Новый ПостроительОтчета;
// В качестве источника данных указываем значение нашего табличного поля.
// Если это список справочника/документа, то используем сам элемент.
// Если табличная часть, то ее нужно выгрузить в ТаблицуЗначений.
// Пример для списка:
// Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ЭлементыФормы.Список);
// Пример для ТаблицыЗначений на форме:
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ЭлементыФормы.МояТаблица.Значение);
// Выполняем построитель и получаем количество строк в результате
КоличествоСтрок = Построитель.Результат.Выбрать().Количество();
Сообщить("Количество строк по данным построителя: " + КоличествоСтрок);
КонецПроцедуры
Важно: Этот метод не будет напрямую учитывать интерактивный отбор, установленный пользователем в табличном поле. Он посчитает строки в источнике данных. Чтобы учесть отбор, его нужно сначала получить из элемента формы и установить для построителя, что усложняет код.
Описанные выше методы в основном актуальны для обычных форм. В управляемых формах для этой задачи есть более элегантное и производительное решение. Оно основано на работе с коллекцией отборов таблицы.
Мы можем просто выгрузить данные из табличной части во временную таблицу значений, передав в метод Выгрузить() текущий отбор, установленный на форме.
// Этот код предназначен для УПРАВЛЯЕМЫХ форм
// Получаем текущую структуру отбора, установленного пользователем в таблице
ОтборТаблицы = Элементы.ИмяВашейТаблицыНаФорме.Отбор.ПолучитьЭлементы();
// Выгружаем данные из источника во временную таблицу, применяя этот отбор
ВременнаяТаблица = Объект.ИмяВашейТабличнойЧасти.Выгрузить(ОтборТаблицы);
// Количество строк во временной таблице и будет искомым значением
КоличествоСтрок = ВременнаяТаблица.Количество();
Сообщить("Количество отфильтрованных строк: " + КоличествоСтрок);
Этот подход является предпочтительным для управляемых форм, так как он использует встроенные механизмы платформы для фильтрации данных на уровне коллекций, что гораздо быстрее ручного перебора. Для готовой организации итогов в подвале табличных частей с учетом отбора на управляемых формах подойдёт набор процедур для расчета итогов табличных частей с отбором.