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