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