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

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

Как рассчитать сумму в 1С: все рабочие способы

Как рассчитать сумму в 1С: итоги в запросе с СУММА и ИТОГИ, функция Сумма в СКД, цикл по таблице значений, типовые ошибки и проверка результата.

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

Главное правило: агрегирование лучше выполнять на уровне запроса, а не перебором строк в цикле. Запрос с функцией СУММА отрабатывает на сервере СУБД и возвращает готовый итог, тогда как цикл по выборке гоняет каждую строку между сервером и клиентом. На больших объёмах разница в скорости — в десятки раз.

Ниже разобраны все практические способы: сумма в запросе, итоги по группам, суммирование таблицы значений и табличной части, расчёт в СКД и типичные ошибки, из-за которых сумма «не сходится».

Сумма в запросе: функция СУММА и секция ИТОГИ

Базовый вариант — агрегатная функция СУММА в тексте запроса. Она складывает значения числового поля по всем строкам выборки или по группам. Значения NULL функция игнорирует, поэтому отдельная обработка NULL обычно не требуется.

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

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

"ВЫБРАТЬ

| СУММА(Продажи.СуммаОборот) КАК СуммаПродаж

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

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

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

ИтоговаяСумма = Выборка.СуммаПродаж;

КонецЕсли;

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

"ВЫБРАТЬ

| Продажи.Контрагент КАК Контрагент,

| СУММА(Продажи.СуммаОборот) КАК Сумма

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

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

| Продажи.Контрагент"

Секция ИТОГИ даёт суммы по группам и общий итог в одном запросе. Результат тогда нужно обходить методом Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам): сначала строки группировок, внутри них — детальные записи. Общий итог без группировки задаётся как ИТОГИ СУММА(Сумма) ПО ОБЩИЕ.

Сумма таблицы значений и табличной части документа

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

// Табличная часть документа

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

// Таблица значений

ИтогоПоКолонке = ТаблицаТоваров.Итог("СуммаНДС");

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

КопияТЗ = ТаблицаТоваров.Скопировать();

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

// Теперь в КопияТЗ одна строка на каждую номенклатуру с суммами

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

Типичные ошибки
01
Свернуть() применён к исходной таблице — детальные строки потеряны безвозвратно, работайте с копией
02
Суммирование строковой колонки: метод Итог() вернёт 0 или ошибку, проверяйте тип колонки
03
Сумма в цикле по выборке из запроса вместо СУММА в тексте запроса — лишние обращения и медленная работа
04
Сравнение суммы с округлением: 0.1 + 0.2 в двоичном представлении даёт погрешность, используйте Окр() перед сравнением

Расчёт суммы в отчёте на СКД

В системе компоновки данных сумма настраивается без кода. На закладке «Ресурсы» конструктора добавьте поле, по которому нужен итог, и укажите выражение Сумма(СуммаОборот). Ресурс будет автоматически рассчитан по каждой группировке отчёта и по общему итогу.

Если сумма должна считаться не по всем группировкам, настройте «Рассчитывать по...» в свойствах ресурса — там перечисляются группировки, для которых ресурс выводится. Это важно, когда сумма по одному разрезу не имеет смысла для другого (например, остаток на конец периода нельзя суммировать по месяцам).

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

Как добавить сумму в отчёт СКД
  1. 1
    Откройте схему компоновки данных отчёта
  2. 2
    На закладке «Ресурсы» добавьте нужное числовое поле
  3. 3
    Укажите выражение Сумма(ИмяПоля) и при необходимости группировки расчёта
  4. 4
    В настройках отчёта добавьте группировки и проверьте общий итог
  5. 5
    Сформируйте отчёт и сверьте итог с контрольным запросом или типовым отчётом

Сумма по данным бухгалтерского учёта

В конфигурациях с бухгалтерским учётом (БП, КА, ERP) суммы по счетам берутся из виртуальных таблиц регистра бухгалтерии Хозрасчетный: Обороты, ОстаткиИОбороты, Остатки. Поле суммы — СуммаОборот, СуммаНачальныйОстаток, СуммаКонечныйОстаток и их дебетовые/кредитовые варианты.

"ВЫБРАТЬ

| ХозрасчетныйОбороты.Субконто1 КАК Контрагент,

| СУММА(ХозрасчетныйОбороты.СуммаОборотДт) КАК СуммаДт

|ИЗ

| РегистрБухгалтерии.Хозрасчетный.Обороты(&Начало, &Конец, , Счет = &Счет62, , ) КАК ХозрасчетныйОбороты

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

| ХозрасчетныйОбороты.Субконто1"

Отбор по счёту и субконто передавайте параметрами виртуальной таблицы. Для счёта с субконто «Контрагенты» значение субконто в полях выборки будет доступно как Субконто1, Субконто2 и т.д. — порядок соответствует виду субконто счёта.

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

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

Общая сумма по запросу
Норма

Совпадает с типовым отчётом (ОСВ, карточка счёта, отчёт по продажам) за тот же период

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

Расхождение — проверьте период, отборы, границу конца периода (включительно ли)

Сумма по группам
Норма

Сумма групп равна общему итогу

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

Часть строк потеряна — проверьте соединения (ЛЕВОЕ вместо ВНУТРЕННЕГО) и NULL в группировочном поле

Сумма таблицы значений
Норма

Итог() равен ручному пересчёту нескольких строк

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

Ноль или ошибка — колонка нечисловая или имя колонки указано с опечаткой

Округление, НДС и точность расчётов

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

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

Для сравнения дробных чисел используйте допуск: вместо строгого равенства проверяйте, что модуль разности меньше 0.01. Это защитит от ложных расхождений из-за особенностей представления дробных чисел.

Если сумма нужна только для показа пользователю на форме, не пишите запрос в коде — добавьте итоговую колонку в подвал динамического списка или таблицы формы через свойство «ПутьКДаннымПоляПодвала». Платформа посчитает итог сама и будет обновлять его автоматически.
ПЗ
Практическое замечание

Производительность: когда сумма считается медленно

Если запрос с СУММА выполняется дольше нескольких секунд, причина почти всегда в объёме читаемых данных. Проверьте: заданы ли параметры виртуальной таблицы (период, отборы), нет ли соединений с детальными таблицами, которые размножают строки до агрегирования, используются ли итоги регистров (для этого период запроса должен попадать в рассчитанные итоги).

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

Итог

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

Данные в базе суммируйте запросом с СУММА и ИТОГИ, таблицы в памяти — методом Итог() или Свернуть(), в отчётах СКД настраивайте ресурсы. Округляйте только финальный результат, отборы передавайте параметрами виртуальных таблиц, а итог всегда сверяйте с типовым отчётом.

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

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

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

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

Получите массив строк методом НайтиСтроки(Новый Структура("Ключ", Значение)) и сложите нужную колонку в цикле. Альтернатива — скопировать таблицу с отбором через Скопировать(Отбор) и применить Итог() к копии.

Чем СУММА отличается от ИТОГИ в запросе?

СУММА — агрегатная функция, дающая один результат на группу. ИТОГИ — секция, которая добавляет в результат запроса дополнительные строки с промежуточными и общими итогами, сохраняя детальные записи. Их часто используют вместе.

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

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

Почему итог в отчёте СКД не совпадает с суммой детальных строк?

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

Можно ли суммировать в запросе значения с разными валютами?

Технически СУММА сложит числа, но результат будет бессмысленным. Сначала пересчитайте суммы в единую валюту через курсы (соединение с регистром сведений курсов на дату документа) и только потом агрегируйте.