Почему не обновляются итоги в подвале таблицы при наложении отбора в управляемых формах 1С?

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

В процессе разработки на платформе 1С:Предприятие 8.3 многие программисты сталкиваются с ситуацией, когда стандартные механизмы ведут себя не так, как ожидалось. Типичный пример — работа с итогами в подвале табличной части управляемой формы. Разберем ситуацию: у нас есть таблица, в свойствах колонок которой настроен автоматический расчет итогов через ПутьКДаннымПодвала. Все работает прекрасно, пока мы не решаем наложить фильтр на строки, например, с помощью свойства ОтборСтрок. В этот момент мы замечаем, что визуально строк стало меньше, но сумма в подвале осталась прежней, как будто никакого отбора нет.

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

Выясним причину: почему автоматика «дает осечку»?

Для начала проанализируем техническую сторону вопроса. В управляемом приложении реализовано четкое разделение между данными (которые живут на сервере в объекте или реквизитах формы) и представлением (тем, что видит пользователь в браузере или тонком клиенте).

Когда мы прописываем в колонке ПутьКДаннымПодвала значение типа Объект.Состав.ИтогСумма, мы даем платформе указание: «Возьми коллекцию данных и вызови у нее встроенный метод получения итога». Этот метод работает напрямую с объектом ТабличнаяЧасть. Однако свойство Элементы.Состав.ОтборСтрок — это инструмент исключительно визуального отображения. Накладывая такой отбор, мы не удаляем строки из коллекции и не меняем сами данные; мы лишь даем команду интерфейсному движку скрыть определенные строки от глаз пользователя.

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

Разберем отличия от «Обычных форм»

Проанализируем опыт прошлых лет. В «Обычных формах» (платформа 8.2 и старше) табличное поле было гораздо сильнее связано с отображаемыми данными. Там существовали механизмы, позволяющие подвалу реагировать на видимость строк. В Управляемом приложении концепция изменилась в сторону «тонкого» клиента, где данные должны передаваться минимальными порциями. Поэтому старые подходы здесь больше не работают, и нам, как разработчикам, приходится брать управление итогами в свои руки.

Способ 1: Ручной пересчет — классический подход

Если нам нужно, чтобы итог соответствовал только видимым (отфильтрованным) строкам, единственный надежный путь — отказаться от использования автоматического пути к данным подвала и реализовать расчет программно. Рассмотрим по шагам, как это сделать правильно.

  1. Создадим реквизит формы: Нам понадобится отдельный реквизит формы (не объекта!), например, с именем ИтогПоОтбору и типом Число.
  2. Настроим подвал колонки: В свойствах элемента формы (колонки таблицы) очистим поле ПутьКДаннымПодвала и вместо него укажем наш новый реквизит ИтогПоОтбору.
  3. Напишем процедуру расчета: Нам нужно создать процедуру, которая будет обходить таблицу и суммировать значения только по тем строкам, которые соответствуют нашему фильтру.

Посмотрим на пример кода, который реализует такой расчет:


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

Эту процедуру необходимо вызывать в тот момент, когда вы устанавливаете или меняете ОтборСтрок. Например, в обработчике нажатия кнопки фильтрации.

Способ 2: Оптимизация с использованием метода «НайтиСтроки»

Проанализируем ситуацию, когда строк в таблице очень много (тысячи). Простой перебор в цикле на клиенте может вызвать кратковременное «замирание» интерфейса. Чтобы ускорить процесс, мы можем воспользоваться методом НайтиСтроки(), который реализован на уровне платформы достаточно эффективно.

Рассмотрим пример реализации:


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

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

Отработка изменения данных (Интерактивность)

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

Чтобы этого избежать, проанализируем необходимые события. Нам нужно привязать вызов процедуры пересчета к событию ПриИзменении соответствующей колонки или всей таблицы. Например:


&НаКлиенте
Процедура СоставПометкаПриИзменении(Элемент)
    // Если наложен отбор, нужно пересчитать итог
    ПересчитатьИтогСУчетомФильтра();
КонецПроцедуры

Таким образом, мы обеспечиваем полную синхронность данных в подвале с тем, что пользователь видит на экране.

Сводная таблица действий для разработчика

Подведем итог нашим действиям, чтобы окончательно закрепить материал:

  1. Осознать: Платформа не делает этот пересчет сама. ОтборСтрок — это декорация, а не изменение данных.
  2. Подготовить форму: Добавить реквизит для итога и связать его с подвалом нужной колонки.
  3. Реализовать логику: Написать функцию обхода строк с проверкой условий фильтра.
  4. Внедрить вызовы: Добавить вызов функции расчета в моменты установки фильтра и при редактировании строк пользователем.

Заключение

Мы проанализировали проблему обновления итогов в управляемых формах 1С и убедились, что стандартное поведение платформы требует от разработчика явного управления данными подвала при использовании фильтров. Несмотря на то, что это требует написания дополнительного кода, такой подход дает полный контроль над логикой приложения и гарантирует корректность отображаемых данных.

Использование ручного пересчета через цикл или метод НайтиСтроки() является общепринятым стандартом разработки (Best Practice) в экосистеме 1С:Предприятие 8.3. Это позволяет избежать недоумения пользователей и делает ваш интерфейс профессиональным и отзывчивым.

← На главную