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

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

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

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

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

Выбор способа зависит от того, где вы работаете — на клиенте в форме, на сервере в модуле объекта или в отчёте. Неправильный выбор приводит либо к лишним обращениям к базе, либо к ошибкам вида «метод не обнаружен», потому что часть методов доступна только в определённом контексте.

Ниже разобраны все рабочие способы с примерами кода, указаны ограничения каждого и типичные ошибки, из-за которых итог считается неверно или не считается вовсе.

Какие способы подсчёта суммы существуют и когда какой выбрать

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

Третий подход — запрос к базе данных с функцией СУММА(). Он оправдан, когда документ ещё не открыт на форме, строк много и нужны итоги сразу по группировкам (например, по номенклатуре или складам). Четвёртый — встроенные механизмы формы: итог по колонке в подвале таблицы и автоматический пересчёт суммы документа типовыми средствами.

Сравнение способов

Метод Итог()

Подходит для простой суммы по одной колонке в форме или модуле объекта. Не умеет фильтровать строки и считать несколько показателей за один проход.

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

Подходит для суммы с условием и параллельного расчёта нескольких итогов. Требует больше кода, но полностью контролируется.

Запрос с СУММА()

Подходит для больших таблиц и группировок без открытия документа. Требует обращения к базе и не работает с несохранёнными строками формы.

Итог в подвале формы

Подходит, когда сумма нужна только визуально пользователю. Не даёт значения для программной логики.

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

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

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

На форме документа обращение идёт через объект:

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

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

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

Подсчёт суммы циклом с условием

Когда нужно просуммировать не все строки, а только часть — например, только товары без учёта услуг или строки по конкретному складу — используется классический цикл:

СуммаТоваров = 0;

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

Если СтрокаТовара.Номенклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Товар Тогда

СуммаТоваров = СуммаТоваров + СтрокаТовара.Сумма;

КонецЕсли;

КонецЦикла;

Цикл незаменим и тогда, когда за один проход нужно посчитать несколько показателей: сумму, количество, сумму НДС, количество строк с ошибками. Это экономит повторные обходы коллекции, что заметно на табличных частях в сотни и тысячи строк.

Обратите внимание на обращение к реквизитам через точку внутри цикла: каждое обращение вида СтрокаТовара.Номенклатура.ВидНоменклатуры на сервере — это потенциальное чтение объекта из базы. На больших объёмах такие обращения замедляют код. Если производительность критична, вынесите получение данных в запрос или используйте значения, уже хранящиеся в строке.

Если в цикле проверяется реквизит ссылочного поля (например, вид номенклатуры), на строках от нескольких сотен код начинает ощутимо тормозить. В таких случаях переносите расчёт в запрос — он получит все нужные поля одним обращением к базе.
ПЗ
Практическое замечание

Расчёт суммы запросом с функцией СУММА

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| СУММА(РеализацияТовары.Сумма) КАК Сумма

|ИЗ

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

|ГДЕ

| РеализацияТовары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

СуммаДокумента = Выборка.Сумма;

КонецЕсли;

Запрос легко расширяется группировкой: добавьте поле в секцию ВЫБРАТЬ и СГРУППИРОВАТЬ ПО — и получите суммы по каждому складу, контрагенту или виду номенклатуры одним обращением. Это принципиально быстрее, чем обход строк с ручной группировкой в соответствии.

Главное ограничение: запрос видит только записанные данные. Если пользователь редактирует документ на форме и строки ещё не сохранены, запрос вернёт старые значения. В контексте формы для незаписанных данных используйте Итог() или цикл.

Автоматический пересчёт итога на форме документа

В типовых конфигурациях сумма документа пересчитывается автоматически при изменении строк. Если вы разрабатываете собственный документ, такое поведение нужно запрограммировать. Стандартное решение — обработчики событий табличной части на форме:

&НаКлиенте

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

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

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

&НаКлиенте

Процедура ТоварыПослеУдаления(Элемент)

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

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

Обработчик ПриИзменении срабатывает при редактировании любого поля строки, ПослеУдаления — при удалении строки. Оба нужны: если подключить только первый, итог не обновится при удалении строки, и пользователь увидит устаревшую сумму.

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

Дополнительная страховка — пересчёт в модуле объекта в обработчике ПередЗаписью. Тогда итог будет корректным даже при программном создании документа из обработки или обмена, когда обработчики формы не выполняются.

Вывод итога в подвал таблицы без программирования

Если сумма нужна только для отображения пользователю и не участвует в логике, проще всего включить итог в подвале таблицы формы. Для этого в конфигураторе у таблицы устанавливается свойство «Подвал» (FooterVisible), а у нужной колонки в свойстве «Текст подвала» или через путь к данным подвала указывается вычисляемый итог.

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

Этот вариант не требует доработки модуля объекта и безопасен: он не влияет на данные, только на представление. Но помните, что программно значение подвала не прочитать — для логики документа всё равно нужен расчёт в коде.

Проверка результата и типичные ошибки

После внедрения расчёта проверьте его на контрольных примерах: документ с одной строкой, документ без строк, документ со строками с нулевой и пустой суммой. Пустая табличная часть должна давать ноль, а не ошибку — Итог() и запрос с СУММА() ведут себя по-разному: запрос вернёт NULL, который нужно обработать через ЕСТЬNULL в запросе или проверку в коде.

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

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

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

Возвращается 0 или обработанный NULL

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

Ошибка выполнения или неинициализированное значение

Итог после удаления строки на форме
Норма

Сумма уменьшается сразу после удаления

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

Сумма остаётся прежней до перезаписи документа

Совпадение с типовым отчётом
Норма

Сумма в коде равна сумме в карточке или отчёте по документу

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

Расхождения — признак фильтрации строк или устаревших данных запроса

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

FAQ

Чем Итог() отличается от запроса с СУММА()?

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

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

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

Почему Итог() возвращает не то значение, что в отчёте?

Чаще всего причина в том, что на форме есть несохранённые изменения, а отчёт читает базу, либо часть строк удалена, но пересчёт не выполнялся. Запишите документ и сравните снова. Если расхождение осталось — проверьте, не фильтруете ли вы строки в одном из расчётов.

Как посчитать сумму по нескольким колонкам одновременно?

Либо вызовите Итог() отдельно для каждой колонки — это просто и читаемо, либо сделайте один цикл с несколькими переменными-накопителями. На больших табличных частях один цикл работает быстрее нескольких вызовов Итог().

Что делать, если запрос с СУММА() возвращает NULL?

Оберните поле в функцию ЕСТЬNULL(СУММА(...), 0) прямо в тексте запроса — тогда при отсутствии строк вернётся ноль. Альтернатива — проверка в коде: Если Выборка.Сумма = NULL Тогда Сумма = 0.

Нужно ли пересчитывать итог при записи документа программно?

Да. Обработчики формы не срабатывают при программном создании и заполнении документа из обработок и обменов. Добавьте пересчёт суммы в обработчик ПередЗаписью модуля объекта — это гарантирует корректный итог при любом способе записи.

Итог

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

Для простой суммы используйте Итог("Сумма"), для суммы с условием — цикл, для группировок и неоткрытых документов — запрос с СУММА() и обработкой NULL. На форме подключайте обработчики ПриИзменении и ПослеУдаления, а в модуле объекта дублируйте пересчёт в ПередЗаписью, чтобы итог был корректен при любом сценарии.