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