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