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