Как рассчитать и вывести итог по колонке в отчете 1С?

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

При самостоятельной разработке печатных форм и отчетов на встроенном языке 1С разработчики часто сталкиваются с ошибкой «Поле объекта не обнаружено (Итого)» или «Метод объекта не обнаружен (Итого)». Выясним причину этой ошибки и разберем правильные способы расчета итоговых сумм по колонкам табличного документа.

Почему возникает ошибка при вызове метода Итого?

Проанализируем исходный фрагмент кода, вызвавший исключительную ситуацию:

ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ТабДок.Итого("СуммаДокумента");

Ошибка вызвана тем, что объект ТабличныйДокумент (как и ВыборкаИзРезультатаЗапроса) не имеет методов Итог() или Итого(). Встроенный метод Итог(ИмяКолонки) существует только у объекта ТаблицаЗначений.

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

Рассмотрим основные способы получения и вывода итоговой суммы.

Способ 1. Накопление суммы в цикле обхода выборки

Это самый простой и быстрый способ, не требующий изменения структуры запроса или выгрузки данных в память. Разберем его по шагам:

  1. Перед циклом обхода выборки инициализируем числовую переменную со значением 0.
  2. Внутри цикла прибавляем к ней значение суммы из текущей строки выборки.
  3. После завершения цикла передаем накопленное значение в параметры области подвала таблицы и выводим область в документ.

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


// Инициализируем переменную для накопления итогов
ИтоговаяСумма = 0;

ТабДок.НачатьАвтогруппировкуСтрок();

ВыборкаДетали = Результат.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
    ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетали);
    ОбластьДетальныхЗаписей.Параметры.ФизЛицоПредставление = СокрЛП(ВыборкаДетали.ФизЛицоПредставление);
    ОбластьДетальныхЗаписей.Параметры.КонтрагентПредставление = СокрЛП(ВыборкаДетали.КонтрагентПредставление);
    ОбластьДетальныхЗаписей.Параметры.ПоДокументу = СокрЛП(ВыборкаДетали.ПоДокументу);
    
    // Накапливаем итог
    ИтоговаяСумма = ИтоговаяСумма + ВыборкаДетали.СуммаДокумента;
    
    ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетали.Уровень());
КонецЦикла;

ТабДок.ЗакончитьАвтогруппировкуСтрок();

// Заполняем и выводим подвал таблицы ПОСЛЕ цикла
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ИтоговаяСумма;
ТабДок.Вывести(ОбластьПодвалТаблицы);

Способ 2. Использование секции ИТОГИ в запросе

Рассмотрим более универсальный механизм платформы 1С — расчет итогов непосредственно средствами языка запросов. Для этого в конец запроса добавляется секция ИТОГИ ПО ОБЩИЕ.

Посмотрим на текст запроса:


Запрос.Текст = 
"ВЫБРАТЬ
|   Доверенность.Номер КАК Номер,
|   Доверенность.Дата КАК Дата,
|   Доверенность.ДатаОкончанияДействия КАК ДатаДействия,
|   Доверенность.СуммаДокумента КАК СуммаДокумента,
|   Доверенность.ФизЛицо КАК ФизЛицо,
|   ПРЕДСТАВЛЕНИЕ(Доверенность.ФизЛицо) КАК ФизЛицоПредставление,
|   ВЫРАЗИТЬ(Доверенность.Контрагент.НаименованиеПолное КАК СТРОКА(200)) КАК КонтрагентПредставление,
|   ВЫРАЗИТЬ(Доверенность.ПоДокументу КАК СТРОКА(200)) КАК ПоДокументу,
|   Доверенность.Ссылка КАК Ссылка
|ИЗ
|   Документ.ДоверенностьВыданная КАК Доверенность
|ГДЕ
|   Доверенность.Организация = &Организация
|   И Доверенность.Дата МЕЖДУ &Дата1 И &Дата2
|УПОРЯДОЧИТЬ ПО
|   Номер
|ИТОГИ
|   СУММА(СуммаДокумента)
|ПО
|   ОБЩИЕ";

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


Результат = Запрос.Выполнить();

// 1. Получаем выборку по группировкам (включая общий итог)
ВыборкаИтоги = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Если ВыборкаИтоги.Следующий() Тогда
    // Заполняем параметр подвала заранее полученной суммой
    ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ВыборкаИтоги.СуммаДокумента;
    
    // 2. Получаем выборку детальных записей внутри группировки
    ВыборкаДетали = ВыборкаИтоги.Выбрать();
    ТабДок.НачатьАвтогруппировкуСтрок();
    
    Пока ВыборкаДетали.Следующий() Цикл
        ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетали);
        ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетали.Уровень());
    КонецЦикла;
    
    ТабДок.ЗакончитьАвтогруппировкуСтрок();
КонецЕсли;

// Выводим область подвала таблицы с уже заполненным итогом
ТабДок.Вывести(ОбластьПодвалТаблицы);

Способ 3. Выгрузка результата запроса в Таблицу Значений

Если требуется использовать именно встроенный метод Итог(), необходимо предварительно выгрузить результат запроса в объект типа ТаблицаЗначений:


ТаблицаРезультата = Результат.Выгрузить();
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ТаблицаРезультата.Итог("СуммаДокумента");

Обратите внимание: данный способ требует выделения дополнительной оперативной памяти под всю таблицу целиком, поэтому при больших объемах данных предпочтительнее использовать Способ 1 или Способ 2.

Оптимизация текста запроса

Проанализируем группировку в исходном запросе. Использование конструкции СГРУППИРОВАТЬ ПО со списком полей, содержащим Доверенность.Ссылка, является избыточным. Поскольку ссылка уникальна для каждого документа, группировка не объединяет строки, а только создает дополнительную нагрузку на СУБД. Рекомендуется убрать секцию СГРУППИРОВАТЬ ПО и агрегатную функцию СУММА() из секции ВЫБРАТЬ, если агрегация на уровне строк документа не требуется.

Альтернатива: Система компоновки данных (СКД)

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

← На главную