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

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

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

Особенности работы с динамическим списком

Прежде всего, проанализируем ситуацию: почему обычный перебор строк таблицы на форме не подходит? Динамический список (ДинамическийСписок) работает по принципу порционного считывания данных. Это означает, что на клиенте в таблице отображаются только те строки, которые видны пользователю в данный момент. Если в базе данных 100 000 путевых листов, а на экране помещается 20, то клиентская часть «знает» только об этих 20 записях. Для расчета корректного итога по всему отбору нам необходимо выполнить запрос на стороне сервера, учитывая все настройки, которые наложил пользователь.

Способ 1: Встроенный механизм платформы (для версии 8.3.10 и выше)

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

Разберем по шагам настройку в конфигураторе:

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

После этой настройки в пользовательском режиме при нажатии кнопки «Еще» — «Настройка списка» появится вкладка Итоги. Пользователь сможет самостоятельно включать и выключать отображение итоговой строки в подвале списка. Платформа сама позаботится о пересчете при изменении поиска или состава отборов — для этого подойдёт инструмент автоматического расчета итогов при фильтрации списка.

Способ 2: Программный расчет итогов через Компоновщик настроек

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

Проанализируем алгоритм действий:

  1. Получаем текущие настройки компоновки данных из динамического списка.
  2. Создаем макет компоновки, используя схему списка и полученные настройки (упростить этот процесс поможет СКДБилдер).
  3. Выполняем запрос и получаем результат суммы.
  4. Записываем результат в реквизит формы, связанный с подвалом колонки.

Посмотрим на пример реализации серверной процедуры:


&НаСервере
Процедура ОбновитьИтогиНаСервере()
    
    // 1. Получаем схему (иногда используются две разных схемы в отчете) и настройки динамического списка
    Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
    Настройки = Список.КомпоновщикНастроек.ПолучитьНастройки();
    
    // 2. Подготавливаем макет компоновки
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    // 3. Выполняем компоновку данных (для сложной обработки пригодится процессор схемы запроса)
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ТаблицаРезультат = Новый ТаблицаЗначений;
    ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // 4. Считаем итог по колонке
    ИтоговаяСумма = ТаблицаРезультат.Итог("СуммаДокумента");
    
    // Записываем в реквизит формы, который отображается в подвале
    ВсегоПоСписку = ИтоговаяСумма;
    
КонецПроцедуры

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

События для обновления итогов

Одной из главных проблем, обсуждаемых программистами, является отсутствие прямого события «ПриИзмененииОтбора» у динамического списка. Чтобы итоги всегда были актуальными, нужно знать, когда вызывать нашу процедуру обновления.

Рассмотрим подробнее доступные механизмы:

Пример использования события формы:


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

&НаКлиенте
Процедура ОбновитьИтогиСЗадержкой()
    ОбновитьИтогиНаСервере();
КонецПроцедуры

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

Рассмотрим ситуацию, когда в списке миллионы записей. Выполнение полного расчета суммы при каждом изменении поиска может привести к существенным задержкам интерфейса («фризам»).

Для оптимизации рекомендуется:

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

← На главную