Как реализовать автоматическое обновление итогов в динамическом списке при изменении данных?

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

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

Метод 1. Использование встроенного механизма итогов динамического списка

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

Разберем этот механизм по шагам:

  1. Откроем форму со списком в конфигураторе.
  2. Выберем основной элемент формы Список (динамический список).
  3. В окне свойств найдем группу параметров «Строка итогов». Установим флаг ИспользоватьСтрокуИтогов.
  4. Для конкретной колонки (пути к данным), по которой нужен итог, в свойстве «Роль» или через программную настройку установим агрегатную функцию (Сумма, Среднее, Количество).

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

Метод 2. Программное инициирование обновления через ОповеститьОбИзменении

Рассмотрим ситуацию, когда данные в базе меняются через API или фоновые задания. В этом случае динамический список на клиенте «не видит» изменений. Чтобы «подтолкнуть» форму к обновлению, на стороне сервера (там, где происходит изменение объекта) следует вызвать метод ОповеститьОбИзменении().

Проанализируем пример кода на сервере:


// Код выполняется после записи объекта (например, в модуле объекта или в REST-сервисе)
СсылкаНаОбъект = Справочники.ЗаказыКлиентов.НайтиПоРеквизиту("ID_API", ЗначениеAPI);
Если Не СсылкаНаОбъект.Пустая() Тогда
    // Сообщаем системе, что данные этого типа или конкретного объекта изменились
    ОповеститьОбИзменении(Тип("СправочникСсылка.ЗаказыКлиентов"));
КонецЕсли;

Когда платформа получает этот сигнал, все открытые динамические списки с данным типом данных автоматически инициируют обновление (выполняют запрос к БД). Это самый «чистый» способ с точки зрения архитектуры 1С.

Метод 3. Использование обработчика ожидания на клиенте

Если изменения вносятся сторонними системами напрямую в СУБД или механизмы оповещения по каким-то причинам не срабатывают, мы можем прибегнуть к использованию периодического обновления. Разберем, как это реализовать правильно, чтобы не перегружать сервер.

В модуле формы в процедуре ПриОткрытии подключим обработчик:


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

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

Важный нюанс: Частое использование метода Обновить() может привести к мерцанию списка и потере текущей позиции курсора у пользователя. Используйте этот метод с осторожностью, устанавливая разумные интервалы времени.

Метод 4. Обработка оповещения (Notify)

Если изменения вносятся пользователями в других формах в рамках одного сеанса, выясним, как передать сигнал в форму списка. Для этого используется пара Оповестить() и ОбработкаОповещения().

В форме объекта (где меняем данные) пишем:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    Оповестить("ИзмененыДанныеДокументов", ПараметрыЗаписи, ЭтаФорма);
КонецПроцедуры

В форме списка перехватываем это событие:


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

Метод 5. Переопределение стандартной команды «Обновить»

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

Чтобы это исправить, выполним следующие шаги:

  1. В командной панели формы найдите стандартную кнопку Обновить.
  2. Снимите у нее флаг «Автозаполнение» в командной панели или удалите стандартную кнопку.
  3. Создайте свою команду формы, например, КомандаОбновить.
  4. Назначьте ей сочетание клавиш F5.
  5. В обработчике команды пропишите обновление списка и ваш расчет.

&НаКлиенте
Процедура КомандаОбновить(Команда)
    Элементы.Список.Обновить();
    РассчитатьИтогиНаСервере();
КонецПроцедуры

Метод 6. Использование события «ПриПолученииДанныхНаСервере»

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

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

Выводы и рекомендации

Мы рассмотрели различные подходы к обновлению итогов. Подведем итог: какой метод выбрать?

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

← На главную