При создании печатных форм одной из самых частых задач является расчет и вывод итоговых показателей: общей суммы документа, общего количества позиций или веса (поможет расчет веса и объема в печатных формах). Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с тем, что в итоговую строку попадает либо только значение последней строки, либо нулевое значение. В этой статье мы подробно разберем, как правильно организовать подсчет итогов несколькими способами, проанализируем типичные ошибки и выясним, какой метод наиболее эффективен в разных ситуациях.
Самый быстрый и простой способ получить сумму по колонке, если данные уже загружены в табличную часть объекта (например, документа), — это использование метода Итог(). Этот метод работает на уровне коллекции строк и не требует написания циклов. Рассмотрим этот подход на примере.
Предположим, у нас есть документ с табличной частью Товары, в которой присутствуют колонки Количество и Сумма. Чтобы передать итоговые значения в параметры макета, мы можем использовать следующий код:
// Получаем итоги напрямую из табличной части объекта
ИтоговоеКоличество = СсылкаНаОбъект.Товары.Итог("Количество");
ИтоговаяСумма = СсылкаНаОбъект.Товары.Итог("Сумма");
// Заполняем параметры области подвала макета
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Параметры.ИтогоКоличество = ИтоговоеКоличество;
ОбластьПодвал.Параметры.ИтогоСумма = ИтоговаяСумма;
ТабДок.Вывести(ОбластьПодвал);
Важный нюанс: данный метод работает только с коллекциями строк (Табличная часть, Таблица значений). Если ваши данные получены через запрос и вы не выгружали их в таблицу, этот метод неприменим напрямую к выборке запроса.
Разберем ситуацию, когда мы обходим выборку данных и выводим строки в макет одну за другой — для этого есть внешняя печатная форма перемещения с итоговой суммой. Часто ошибка заключается в том, что разработчик внутри цикла просто присваивает параметру значение текущей строки, вместо того чтобы суммировать его с предыдущими. Проанализируем правильную логику накопления суммы.
Рассмотрим пошагово, как реализовать счетчик (поможет вывод итоговых весо-объемных показателей в макет 1С):
// Инициализируем переменные для накопления итогов
ВсегоКоличество = 0;
ВсегоСумма = 0;
Пока ВыборкаСтрок.Следующий() Цикл
// Выводим текущую строку товара
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Заполнить(ВыборкаСтрок);
ТабДок.Вывести(ОбластьСтрока);
// Накапливаем итоги: текущее значение прибавляем к накопленному
ВсегоКоличество = ВсегоКоличество + ВыборкаСтрок.Количество;
ВсегоСумма = ВсегоСумма + ВыборкаСтрок.Сумма;
КонецЦикла;
// После завершения цикла выводим итоги в область подвала
ОбластьИтоги = Макет.ПолучитьОбласть("Итог");
ОбластьИтоги.Параметры.ВсегоКоличество = ВсегоКоличество;
ОбластьИтоги.Параметры.ВсегоСумма = ВсегоСумма;
ТабДок.Вывести(ОбластьИтоги);
В данном примере мы используем конструкцию ВсегоСумма = ВсегоСумма + ВыборкаСтрок.Сумма. Если написать просто ВсегоСумма = ВыборкаСтрок.Сумма, то в переменную запишется значение только из последней итерации цикла, что и является основной причиной "пропажи" итогов у новичков.
Проанализируем наиболее профессиональный и производительный подход — расчет итогов непосредственно в запросе (удобно через разработка макетов с расчетом итогов без программирования). Система компоновки данных или обычный запрос могут вернуть уже готовые агрегатные значения. Это избавляет от необходимости нагружать память сервера лишними операциями сложения в цикле.
Для этого в тексте запроса используется ключевое слово ИТОГИ. Рассмотрим пример текста запроса:
ТекстЗапроса = "
|ВЫБРАТЬ
| Товары.Номенклатура,
| Товары.Количество,
| Товары.Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|ИТОГИ
| СУММА(Количество),
| СУММА(Сумма)
|ПО
| ОБЩИЕ";
При использовании ИТОГИ ПО ОБЩИЕ выборка из результата запроса будет содержать специальную строку с общими суммами. Выясним, как правильно обработать такую выборку:
РезультатЗапроса = Запрос.Выполнить();
// Выборка по общим итогам (первая и единственная строка верхнего уровня)
ВыборкаИтог = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Если ВыборкаИтог.Следующий() Тогда
// Записываем общие итоги сразу в параметры подвала
ОбластьПодвал.Параметры.ИтогоКоличество = ВыборкаИтог.Количество;
ОбластьПодвал.Параметры.ИтогоСумма = ВыборкаИтог.Сумма;
// Теперь переходим к детальным записям (строкам товаров)
ВыборкаДетали = ВыборкаИтог.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
// Вывод строк макета...
КонецЦикла;
КонецЕсли;
Посмотрим на ситуацию с точки зрения пользователя. Итоговая сумма в бухгалтерских документах должна быть не только числовой, но и расшифрованной текстом (прописью). В 1С для этого предусмотрена мощная функция ЧислоПрописью(). Разберем, как ее правильно внедрить в подвал печатной формы — для этого есть конструктор макетов с автоматическим выводом суммы прописью.
Пример формирования строки "Итого прописью":
// Формируем форматную строку для валюты (Рубли)
ФорматнаяСтрока = "L=ru_RU; SN=рубль, рубля, рублей, м, копейка, копейки, копеек, ж, 2";
СуммаПрописьюТекст = ЧислоПрописью(ВсегоСумма, "L=ru_RU", ФорматнаяСтрока);
// Выводим в макет
ОбластьПодвал.Параметры.СуммаПрописью = СуммаПрописьюТекст;
Полезный совет: для визуального разделения тысяч в больших числах используйте оформление ячейки в самом макете. В свойствах ячейки, в поле "Формат", установите значение ЧЦ=15; ЧДЦ=2; ЧГ=3,0. Это позволит выводить сумму в виде 1 250 300,50 вместо сплошного текста 1250300.5, что значительно повышает читаемость документа.
Рассмотрим более сложный случай, когда документ занимает несколько страниц. В профессиональных печатных формах часто требуется выводить промежуточные итоги внизу каждой страницы ("Итого по странице").
Для реализации этого механизма мы должны перед выводом каждой строки проверять, помещается ли она на текущий лист:
Ложь, значит, строка не влезает. В этом случае выводим область "Итого на странице", вставляем разрыв страницы и обнуляем текущий счетчик страницы.Этот подход гарантирует, что ваши итоги всегда будут логически завершать каждую страницу печатного документа, что соответствует государственным стандартам оформления многих первичных документов.
Подводя итог, можно сказать: выбор метода зависит от архитектуры вашего решения. Для простых форм достаточно Итог() по табличной части, для сложных отчетов с группировками лучше использовать ИТОГИ в запросе, а для контроля переноса строк — ручное накопление в цикле с проверкой вывода.