К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как посчитать итоги в табличной части 1С

Как посчитать итоги по колонке табличной части в 1С: метод Итог(), цикл, итоги на форме, итоги в запросе. Примеры кода, ошибки и проверка результата.

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

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

Ниже разобраны все рабочие варианты с примерами кода, указаны типичные ошибки (например, попытка вызвать Итог() у таблицы значений или получить итог по несуществующей колонке) и способы проверить корректность результата.

Метод Итог(): самый простой способ

У табличной части объекта (документа, справочника) есть встроенный метод Итог(), который суммирует значения числовой колонки по всем строкам. Это стандартное решение, когда нужна простая сумма без условий.

// В модуле объекта или формы документа

СуммаПоДокументу = Объект.Товары.Итог("Сумма");

КоличествоВсего = Объект.Товары.Итог("Количество");

СуммаНДС = Объект.Товары.Итог("СуммаНДС");

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

Важный нюанс: Итог() работает у табличных частей объектов и у таблиц значений. А вот у динамического списка или результата запроса этого метода нет — там нужны другие подходы, описанные ниже.

Подсчёт итогов циклом: когда нужны условия

Если суммировать нужно не все строки, а только часть — например, только строки с конкретной номенклатурой, складом или признаком — метод Итог() не подходит. Задача решается обходом строк в цикле.

СуммаУслуг = 0;

Для Каждого СтрокаТовары Из Объект.Товары Цикл

Если СтрокаТовары.Номенклатура.Услуга Тогда

СуммаУслуг = СуммаУслуг + СтрокаТовары.Сумма;

КонецЕсли;

КонецЦикла;

Цикл даёт полную гибкость: можно считать несколько итогов за один проход, применять сколь угодно сложные условия, округлять промежуточные значения. Для табличных частей типового размера (десятки и сотни строк) разница в скорости с Итог() незаметна.

Альтернатива без цикла — выгрузить табличную часть в таблицу значений, свернуть или отобрать строки и потом посчитать итог:

ТЗ = Объект.Товары.Выгрузить();

ТЗ.Свернуть("Склад", "Сумма,Количество");

// Теперь в ТЗ по одной строке на склад с итогами по нему

Сравнение вариантов

Итог()

Простая сумма по всей колонке. Самый короткий код, но без условий отбора.

Цикл по строкам

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

Выгрузить() + Свернуть()

Итоги в разрезе групп (склад, контрагент, ставка НДС). Требует дополнительной памяти под копию таблицы.

Запрос с ИТОГИ

Итоги по данным из базы без загрузки объекта целиком. Оптимально для больших выборок и отчётов.

Итоги в запросе: конструкция ИТОГИ

Когда данные лежат в базе и объект загружать в память не нужно, итоги эффективнее считать запросом. Конструкция ИТОГИ добавляет в результат итоговые записи — общие или по группировочным полям.

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

СУММА(Товары.Количество) КАК Количество,

СУММА(Товары.Сумма) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

ГДЕ

Товары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО

Товары.Номенклатура

ИТОГИ

СУММА(Количество),

СУММА(Сумма)

ПО

ОБЩИЕ

Чтобы получить один общий итог, после выполнения запроса выберите итоговую запись: Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) и прочитайте первую запись. Для итогов в разрезе групп укажите ИТОГИ ... ПО Номенклатура и обходите выборку по группировкам.

Запрос особенно выигрывает, когда итоги нужны сразу по многим документам: один запрос к базе заменяет загрузку каждого объекта и обход его табличных частей в цикле.

bsl
Запрос = Новый Запрос("ВЫБРАТЬ СУММА(Т.Сумма) КАК ИтогоСумма ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Т ГДЕ Т.Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    ИтогоПоДокументу = Выборка.ИтогоСумма;
КонецЕсли;

Итоги на форме: подвал таблицы и реквизиты

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

Типовой приём в управляемых формах: в свойстве колонки подвала указать путь к данным шапки, например Объект.СуммаДокумента, а сам реквизит пересчитывать в обработчике ПриИзменении табличной части:

&НаКлиенте

Процедура ТоварыПриИзменении(Элемент)

Объект.СуммаДокумента = Объект.Товары.Итог("Сумма");

КонецПроцедуры

Обработчик ПриИзменении срабатывает при добавлении, удалении и редактировании строк, поэтому итог в шапке всегда актуален. Если пересчёт тяжёлый (запросы к базе), вызывайте его на сервере и не делайте лишних обращений при каждом нажатии клавиши — пересчитывайте по окончании редактирования строки.

Порядок действий для итога на форме
  1. 1
    Добавьте в объект реквизит шапки для итога, например СуммаДокумента (число)
  2. 2
    В модуле формы создайте обработчик ТоварыПриИзменении
  3. 3
    Внутри присвойте реквизиту значение Объект.Товары.Итог("Сумма")
  4. 4
    В редакторе формы включите у таблицы свойство Подвал
  5. 5
    Проверьте: добавьте и удалите строки — итог должен обновляться автоматически

Итоги в печатных формах и отчётах

В макете печатной формы итоги обычно выводятся в отдельной области «Подвал» или «Итого». Значения для неё считаются заранее — тем же Итог() или запросом — и подставляются как параметры:

ОбластьИтог = Макет.ПолучитьОбласть("Итого");

ОбластьИтог.Параметры.ВсегоСумма = Объект.Товары.Итог("Сумма");

ОбластьИтог.Параметры.ВсегоНДС = Объект.Товары.Итог("СуммаНДС");

ТабДок.Вывести(ОбластьИтог);

В отчётах на СКД итоги считает сама система компоновки: достаточно в настройках отчёта добавить ресурс (например, «Сумма» с агрегатом «Сумма») и включить общие итоги. Вручную ничего обходить не нужно — СКД строит группировки и итоги по ним автоматически.

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

Типичные ошибки
01
Вызов Итог() у результата запроса или динамического списка — метода там нет, будет ошибка выполнения
02
Опечатка в имени колонки: Итог("Суммы") вместо Итог("Сумма") — ошибка обнаружится только в момент выполнения
03
Пересчёт итога только в ПриИзменении одной колонки: при удалении строки итог устаревает — используйте обработчик всей таблицы
04
Суммирование в цикле без инициализации переменной нулём — итог накапливается между вызовами
05
Округление строк при выводе, а итога — по сырым данным: копеечные расхождения в печатной форме

Производительность и проверка результата

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

Ещё одна ловушка — пересчёт итогов на клиенте при каждом изменении с обращением к серверу. В тонком клиенте каждый серверный вызов — это сетевой обмен. Держите пересчёт в клиентском обработчике (метод Итог() доступен на клиенте) и выносите на сервер только то, что требует данных базы.

Проверять результат удобно по контрольным точкам: итог пустой табличной части должен быть 0, а не NULL или ошибка; итог после добавления строки должен увеличиться ровно на сумму строки; итог в шапке должен совпадать с итогом подвала таблицы на форме и с суммой в печатной форме.

Контрольные точки

Как проверить результат

Итог пустой табличной части
Норма

Возвращается 0

Тревожный признак

Ошибка выполнения или NULL

Добавление строки на 100 руб.
Норма

Итог увеличился ровно на 100

Тревожный признак

Итог не изменился или изменился непропорционально

Итог в шапке и в подвале таблицы
Норма

Значения совпадают

Тревожный признак

Расхождение — пересчёт вызывается не во всех обработчиках

Печатная форма
Норма

Итог равен сумме отображаемых строк

Тревожный признак

Копеечные расхождения из-за округления

Итог

Что важно запомнить

Простая сумма — метод Итог("Колонка"). Итоги с условиями — цикл или Свернуть(). Итоги по базе без загрузки объектов — запрос с ИТОГИ. На форме — подвал таблицы и пересчёт в обработчике ПриИзменении. Всегда проверяйте итог на пустой таблице и на совпадение с суммой строк.

Частые вопросы

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

Обойдите коллекцию выделенных строк: Для Каждого ИдСтроки Из Элементы.Товары.ВыделенныеСтроки Цикл, получайте строку через Объект.Товары.НайтиПоИдентификатору(ИдСтроки) и суммируйте нужное поле. Готового метода для выделенных строк нет.

Можно ли вызвать Итог() у таблицы значений?

Да, у таблицы значений есть метод Итог("ИмяКолонки") — он работает так же, как у табличной части. Часто используется связка: Объект.Товары.Выгрузить(), далее отбор или свёртка, затем Итог() по результату.

Почему Итог() возвращает 0, хотя строки заполнены?

Чаще всего имя колонки указано с ошибкой или колонка нечисловая. Также проверьте, что суммируете тот реквизит, который реально заполняется: например, сумма может храниться в реквизите «Всего», а не «Сумма». Посмотрите точные имена в конфигураторе.

Как вывести итог по колонке динамического списка?

У динамического списка метода Итог() нет, потому что данные подгружаются порциями. Решения: выполнить тот же запрос с ИТОГИ отдельно и показать результат в реквизите формы, либо заменить динамический список таблицей значений, если объём данных позволяет.

Чем отличается Итог() от Свернуть()?

Итог() возвращает одно число — сумму по колонке. Свернуть() изменяет саму таблицу: группирует строки по указанным колонкам и суммирует числовые поля в каждой группе. Используйте Свернуть(), когда нужны итоги в разрезе — по складам, контрагентам, ставкам НДС.

Где правильно хранить итог документа: в реквизите или считать на лету?

Типовая практика — хранить итог в реквизите шапки (например, «СуммаДокумента») и пересчитывать его при изменении табличной части. Это ускоряет списки и отчёты, где сумма показывается без открытия документа. Считать на лету оправдано только для редко используемых показателей.