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

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

При разработке интерфейсов на управляемых формах разработчики часто сталкиваются с задачей: необходимо динамически пересчитывать итоги в подвале табличной части или отображать сумму только по тем строкам, которые пользователь отобрал через поиск по Ctrl + F. Однако стандартное поведение платформы 1С:Предприятие 8.3 имеет ряд фундаментальных ограничений.

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

Причина проблемы и особенности платформы 1С

Проанализируем поведение управляемой формы при работе с различными источниками данных:

  1. Динамические списки: формируются на сервере с помощью языка запросов и СКД. Для них существуют события и механизмы получения исполняемых настроек компоновки данных.
  2. Табличные части и таблицы значений: данные целиком находятся в памяти клиента/сервера в виде прикладного объекта или реквизита формы. Интерактивный поиск по Ctrl + F и отбор по текущему значению выполняются исключительно на стороне тонкого клиента для визуального отображения строк.

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

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

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

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


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

Для регулярного обновления значения суммы подключим вызов этой процедуры через фоновый опрос или стандартные клиентские события:

  1. Подключение обработчика ожидания: при открытии формы запускаем опрос состояния таблицы раз в 1 секунду.
  2. События интерфейса: вызываем расчет в событиях таблицы ПриАктивизацииСтроки, ПриАктивизацииЯчейки и ПриИзменении элементов ввода.

Посмотрим, как организовать процедуру с обработчиком ожидания:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ПодключитьОбработчикОжидания("ФоновыйПересчетИтогов", 1, Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ФоновыйПересчетИтогов()
    СуммаПоВидимым = РассчитатьИтогПоВидимымСтрокам();
    // Выводим полученную сумму в отдельный реквизит формы или надпись
    Элементы.НадписьИтоговаяСумма.Заголовок = "Итого (по фильтру): " + Формат(СуммаПоВидимым, "ЧДЦ=2; ЧГ=3,0");
КонецПроцедуры

Способ 2. Перехват сочетания клавиш Ctrl+F и собственный поиск

Если требуется полный контроль над моментом установки отбора и недопустима работа фоновых процедур, разберем по шагам альтернативное решение — замену стандартного поиска платформы собственной командой:

  1. Отключение стандартных кнопок: в командной панели таблицы формы отключаем автозаполнение либо скрываем стандартные команды Поиск и ОтменитьПоиск.
  2. Отключение поиска при вводе текста: в свойствах таблицы формы устанавливаем свойство АвтоматическийПоискПриНабореТекста в значение НеИспользовать.
  3. Создание пользовательской команды: создаем команду формы, например НайтиВСписке, и назначаем ей сочетание клавиш Ctrl + F.
  4. Реализация логики: в обработчике команды запрашиваем у пользователя строку поиска через ВвестиСтроку() или отдельную панель, после чего программно накладываем фильтр на таблицу и сразу пересчитываем итоги.

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


&НаКлиенте
Процедура КомандаПоиск(Команда)
    
    Подсказка = "Введите строку для поиска:";
    ВведенныйТекст = "";
    
    Оповещение = Новый ОписаниеОповещения("ПослеВводаСтрокиПоиска", ЭтотОбъект);
    ПоказатьВводСтроки(Оповещение, ВведенныйТекст, Подсказка);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаСтрокиПоиска(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Выполняем собственный отбор и расчет итогов
    ВыполнитьПользовательскийОтбор(Результат);
    
КонецПроцедуры

Оптимизация производительности

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

В таких случаях рекомендуется запускать пересчет не периодически, а однократно с небольшой задержкой (0.3–0.5 секунды) после срабатывания событий взаимодействия пользователя с таблицей (ПриАктивизацииСтроки), отключая и взводя однократный обработчик ожидания заново.

← На главную