Как получить количество видимых строк в таблице управляемой формы после поиска

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

В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача отображения итогов по таблице, которая находится непосредственно на форме (например, связанная с ТаблицейЗначений или ТабличнойЧастью). Особую сложность вызывает ситуация, когда пользователь применяет стандартную команду "Найти" (вызываемую через Ctrl+F или контекстное меню). Стандартные механизмы платформы визуально скрывают строки, не подходящие под критерии поиска, но программно количество строк в самой коллекции данных (объекте) не меняется. В этой статье мы подробно разберем, как вычислить количество фактически видимых пользователю строк и где лучше всего разместить этот код.

Суть проблемы и поиск решения

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

Основной инструмент: метод ПроверитьСтроку()

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

  1. Стандартный поиск (команда "Найти").
  2. Отбор по значению в текущей колонке.
  3. Программный ОтборСтрок, установленный через расширение таблицы.

Метод ПроверитьСтроку() доступен только на клиенте и принимает в качестве параметра идентификатор строки. Если строка видима пользователю, метод возвращает Истина.

Алгоритм реализации подсчета

Разберем по шагам, как реализовать механизм подсчета. Нам потребуется создать процедуру, которая будет обходить коллекцию данных и проверять каждую строку на "видимость".

Для начала создадим на форме реквизит КоличествоВидимыхСтрок (тип "Число"). Выведем его на форму в виде надписи или в подвал соответствующей колонки таблицы. Теперь напишем клиентскую процедуру для пересчета:


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

Выбор события для запуска пересчета

Выясним причину, по которой это решение не всегда работает автоматически. Главный вопрос: когда вызывать эту процедуру? Поскольку явного события завершения поиска нет, рассмотрим основные варианты:

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

Рассмотрим пример реализации через ПриОбновленииОтображения с защитой от лишних вычислений:


&НаКлиенте
Процедура ПриОбновленииОтображения()
    // Используем ПодключитьОбработчикОжидания, чтобы расчет 
    // не "вешал" интерфейс при каждом движении мыши
    ПодключитьОбработчикОжидания("ВыполнитьОтложенныйПересчет", 0.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОтложенныйПересчет()
    ПересчитатьКоличествоВидимыхСтрок();
КонецПроцедуры

Альтернативный подход для сложных итогов (через СКД)

Если вам нужно не просто посчитать количество строк, а вычислить сумму, среднее или другие сложные агрегатные функции по отфильтрованным данным, обычного цикла на клиенте может быть недостаточно из-за низкой производительности. В этом случае проанализируем ситуацию с использованием Системы Компоновки Данных (СКД).

Если ваша таблица — это ДинамическийСписок, вы можете на сервере получить исполняемую схему и настройки, чтобы выполнить запрос с учетом всех пользовательских отборов. Посмотрим на пример кода, который позволяет получить результат компоновки данных:


&НаСервере
Функция ПолучитьКоличествоЧерезСКД()
    
    Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
    Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    РезультатТЗ = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    Возврат РезультатТЗ.Количество();
    
КонецФункции

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

Особенности работы с программными отборами

Важно различать ОтборСтрок и интерактивный поиск. Если вы программно устанавливаете Элементы.Таблица.ОтборСтрок, это свойство ограничивает набор данных на уровне отображения элемента. Метод ПроверитьСтроку() корректно обработает и этот случай. Однако помните, что интерактивный поиск "Найти" работает поверх ваших программных отборов. Таким образом, использование цикла с проверкой каждой строки является максимально надежным способом получить именно то число, которое пользователь видит на своем экране в данный момент.

Рекомендации по оптимизации

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

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

← На главную