При самостоятельной разработке печатных форм и отчетов на встроенном языке 1С разработчики часто сталкиваются с ошибкой «Поле объекта не обнаружено (Итого)» или «Метод объекта не обнаружен (Итого)». Выясним причину этой ошибки и разберем правильные способы расчета итоговых сумм по колонкам табличного документа.
Проанализируем исходный фрагмент кода, вызвавший исключительную ситуацию:
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ТабДок.Итого("СуммаДокумента");
Ошибка вызвана тем, что объект ТабличныйДокумент (как и ВыборкаИзРезультатаЗапроса) не имеет методов Итог() или Итого(). Встроенный метод Итог(ИмяКолонки) существует только у объекта ТаблицаЗначений.
Кроме того, обратим внимание на порядок вывода областей в коде: подвал таблицы пытались заполнить и вывести до детальных записей, после чего вызывался метод ТабДок.Очистить(), удалявший весь сформированный контент. Подвал отчета должен выводиться строго после завершения вывода строк таблицы.
Рассмотрим основные способы получения и вывода итоговой суммы.
Это самый простой и быстрый способ, не требующий изменения структуры запроса или выгрузки данных в память. Разберем его по шагам:
Посмотрим на пример реализации:
// Инициализируем переменную для накопления итогов
ИтоговаяСумма = 0;
ТабДок.НачатьАвтогруппировкуСтрок();
ВыборкаДетали = Результат.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетали);
ОбластьДетальныхЗаписей.Параметры.ФизЛицоПредставление = СокрЛП(ВыборкаДетали.ФизЛицоПредставление);
ОбластьДетальныхЗаписей.Параметры.КонтрагентПредставление = СокрЛП(ВыборкаДетали.КонтрагентПредставление);
ОбластьДетальныхЗаписей.Параметры.ПоДокументу = СокрЛП(ВыборкаДетали.ПоДокументу);
// Накапливаем итог
ИтоговаяСумма = ИтоговаяСумма + ВыборкаДетали.СуммаДокумента;
ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетали.Уровень());
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();
// Заполняем и выводим подвал таблицы ПОСЛЕ цикла
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ИтоговаяСумма;
ТабДок.Вывести(ОбластьПодвалТаблицы);
Рассмотрим более универсальный механизм платформы 1С — расчет итогов непосредственно средствами языка запросов. Для этого в конец запроса добавляется секция ИТОГИ ПО ОБЩИЕ.
Посмотрим на текст запроса:
Запрос.Текст =
"ВЫБРАТЬ
| Доверенность.Номер КАК Номер,
| Доверенность.Дата КАК Дата,
| Доверенность.ДатаОкончанияДействия КАК ДатаДействия,
| Доверенность.СуммаДокумента КАК СуммаДокумента,
| Доверенность.ФизЛицо КАК ФизЛицо,
| ПРЕДСТАВЛЕНИЕ(Доверенность.ФизЛицо) КАК ФизЛицоПредставление,
| ВЫРАЗИТЬ(Доверенность.Контрагент.НаименованиеПолное КАК СТРОКА(200)) КАК КонтрагентПредставление,
| ВЫРАЗИТЬ(Доверенность.ПоДокументу КАК СТРОКА(200)) КАК ПоДокументу,
| Доверенность.Ссылка КАК Ссылка
|ИЗ
| Документ.ДоверенностьВыданная КАК Доверенность
|ГДЕ
| Доверенность.Организация = &Организация
| И Доверенность.Дата МЕЖДУ &Дата1 И &Дата2
|УПОРЯДОЧИТЬ ПО
| Номер
|ИТОГИ
| СУММА(СуммаДокумента)
|ПО
| ОБЩИЕ";
При таком подходе обход выборки строится в два уровня: сначала получаем группировку общих итогов, а затем — детальные записи:
Результат = Запрос.Выполнить();
// 1. Получаем выборку по группировкам (включая общий итог)
ВыборкаИтоги = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Если ВыборкаИтоги.Следующий() Тогда
// Заполняем параметр подвала заранее полученной суммой
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ВыборкаИтоги.СуммаДокумента;
// 2. Получаем выборку детальных записей внутри группировки
ВыборкаДетали = ВыборкаИтоги.Выбрать();
ТабДок.НачатьАвтогруппировкуСтрок();
Пока ВыборкаДетали.Следующий() Цикл
ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетали);
ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетали.Уровень());
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();
КонецЕсли;
// Выводим область подвала таблицы с уже заполненным итогом
ТабДок.Вывести(ОбластьПодвалТаблицы);
Если требуется использовать именно встроенный метод Итог(), необходимо предварительно выгрузить результат запроса в объект типа ТаблицаЗначений:
ТаблицаРезультата = Результат.Выгрузить();
ОбластьПодвалТаблицы.Параметры.ИтогоСумма = ТаблицаРезультата.Итог("СуммаДокумента");
Обратите внимание: данный способ требует выделения дополнительной оперативной памяти под всю таблицу целиком, поэтому при больших объемах данных предпочтительнее использовать Способ 1 или Способ 2.
Проанализируем группировку в исходном запросе. Использование конструкции СГРУППИРОВАТЬ ПО со списком полей, содержащим Доверенность.Ссылка, является избыточным. Поскольку ссылка уникальна для каждого документа, группировка не объединяет строки, а только создает дополнительную нагрузку на СУБД. Рекомендуется убрать секцию СГРУППИРОВАТЬ ПО и агрегатную функцию СУММА() из секции ВЫБРАТЬ, если агрегация на уровне строк документа не требуется.
Для создания отчетов со сложными структурами, группировками и итогами рекомендуется переходить на Систему компоновки данных (СКД). При использовании СКД расчет общих и промежуточных итогов по полям ресурсов (таким как СуммаДокумента) выполняется платформой автоматически без необходимости ручного программирования вывода ячеек и подсчета сумм.