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

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

Как вычислить сумму в документе 1С

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

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

Главное правило: сумму документа не стоит хранить как отдельный реквизит, если её можно вычислить из табличной части. Хранимая сумма легко расходится с реальными строками при редактировании документа, а вычисляемое значение всегда актуально. Исключение — реквизиты, которые фиксируют сумму на момент проведения для истории или обмена с внешними системами.

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

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

В типовых конфигурациях (УТ, ERP, Бухгалтерия) сумма документа складывается из сумм строк табличной части. Каждая строка содержит количество, цену и сумму, а итог по документу вычисляется динамически и отображается внизу формы табличной части.

Цепочка расчёта в строке обычно такая: при изменении количества или цены пересчитывается сумма строки, затем по сумме строки рассчитывается сумма НДС, и наконец сумма с НДС. Всё это выполняют обработчики событий формы — ПриИзменении у полей «Количество» и «Цена».

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

Расчёт суммы строки при изменении количества или цены

Для собственного документа расчёт суммы строки делается в модуле формы. На поля «Количество» и «Цена» табличной части назначается обработчик ПриИзменении, который умножает значения и записывает результат в колонку «Сумма».

&НаКлиенте

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

РассчитатьСуммуСтроки();

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

&НаКлиенте

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

РассчитатьСуммуСтроки();

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

&НаКлиенте

Процедура РассчитатьСуммуСтроки()

Строка = Элементы.Товары.ТекущиеДанные;

Если Строка = Неопределено Тогда

Возврат;

КонецЕсли;

Строка.Сумма = Строка.Количество * Строка.Цена;

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

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

Вычисление итоговой суммы методом Итог()

Самый быстрый способ получить сумму по всему документу — метод табличной части Итог("ИмяКолонки"). Он возвращает сумму значений указанной колонки по всем строкам без явного перебора.

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

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

ИтогоСНДС = СуммаДокумента + СуммаНДС;

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

Ограничение метода: он суммирует только одну колонку и не позволяет задать условие. Если нужна сумма только по строкам с определённым признаком (например, только по товарам конкретного склада), потребуется перебор или запрос.

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

Перебор строк с накоплением суммы

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

СуммаИтог = 0;

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

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

Продолжить;

КонецЕсли;

СуммаИтог = СуммаИтог + СтрокаТовары.Количество * СтрокаТовары.Цена;

КонецЦикла;

Перебор незаменим при проведении документа: в модуле объекта по строкам формируются движения, и одновременно накапливается итог для контроля или записи в регистр. Там же удобно проверять отрицательные остатки и превышение лимитов.

Учтите, что при большом числе строк (десятки тысяч) перебор в цикле работает медленнее запроса, особенно если внутри цикла выполняются обращения к базе. Для тяжёлых расчётов предпочтителен запрос.

Сумма по документу через запрос

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

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

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

"ВЫБРАТЬ

| СУММА(Товары.Сумма) КАК СуммаДокумента

|ИЗ

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

|ГДЕ

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

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

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

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

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

КонецЕсли;

Запрос выполняется на сервере и не требует получения объекта документа целиком, что существенно быстрее при работе с большими объёмами. Если документов нет или табличная часть пуста, СУММА() вернёт NULL — обрабатывайте это через ЕСТЬNULL().

Для группировки итогов по нескольким документам добавьте СГРУППИРОВАТЬ ПО по ссылке или контрагенту — так одним запросом получают суммы по целому списку реализаций за период.

Порядок вычисления суммы документа запросом
  1. 1
    Определите, по какой табличной части и колонке считается итог
  2. 2
    Составьте запрос с СУММА() и отбором по ссылке
  3. 3
    Оберните результат в ЕСТЬNULL(СУММА(...), 0)
  4. 4
    Выполните запрос и проверьте результат на тестовом документе
  5. 5
    Сверьте итог с суммой, отображаемой в форме документа

Выбор способа под задачу

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

Сравнение способов вычисления суммы

Итог()

Быстро и просто для одного документа в форме или модуле объекта; не поддерживает условия по строкам

Перебор строк

Подходит при фильтрации и дополнительной логике по строкам; медленнее на больших табличных частях

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

Оптимален для отчётов и массовой обработки документов; требует обработки NULL и работает только на сервере

Вычисляемое поле формы

Для отображения итога пользователю в шапке документа; не годится для проведения и обменов

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

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

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

Типичные ошибки
01
Хранение суммы документа отдельным реквизитом без пересчёта — итог расходится со строками после редактирования
02
Игнорирование NULL из запроса — при пустой табличной части вместо нуля получают ошибку приведения типа
03
Расчёт суммы строки без учёта НДС и скидок — итог не сходится с типовой печатной формой
04
Вызов серверного запроса из клиентского обработчика ПриИзменении — ошибка контекста в управляемой форме
05
Округление суммы каждой строки по-разному — копеечные расхождения в итоге документа

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

Итог

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

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

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

Как вывести общую сумму документа в шапке формы?

Создайте реквизит формы, например «ИтогоСумма», разместите его на форме и обновляйте в обработчиках изменения табличной части: ИтогоСумма = Объект.Товары.Итог("Сумма");. Вызов обновления добавьте также в обработчик после удаления строки и после окончания редактирования строки.

Почему запрос с СУММА() возвращает NULL?

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

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

Метод Итог() условий не поддерживает, поэтому используйте перебор: в цикле проверяйте признак строки (например, флажок «Отмечено») и накапливайте сумму только для подходящих строк. Альтернатива — запрос с отбором по значению колонки-флажка.

Чем отличается сумма в форме от суммы в проводках?

Сумма на форме — это итог табличной части на текущий момент, а в проводках сумма фиксируется при проведении с учётом НДС, курсов и округлений. Если документ редактировали после проведения без перепроведения, значения могут различаться — перепроведите документ.

Как получить сумму прописью для печатной формы?

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

Можно ли вычислить сумму на клиенте без вызова сервера?

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