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