В рамках этой темы мы подробно рассмотрим, как правильно использовать агрегатные функции для получения итоговых данных по табличным частям в шаблонах договоров, например, в 1С:Управление торговлей 11. Часто пользователи сталкиваются с проблемой, когда функции вроде СуммаПоКолонке или КоличествоСтрок выводятся построчно или некорректно. Мы выясним причины такого поведения и предложим проверенные решения, включая подходы для обработки вычисляемых колонок.
Первоначально пользователь сталкивается с тем, что прямые попытки использования функций, таких как СуммаПоКолонке("Товары.Сумма") или КоличествоСтрок.[Товары], приводят к некорректному выводу: либо текст функции выводится как есть, либо итог повторяется для каждой строки табличной части. Это происходит из-за неправильного размещения этих функций в макете печатной формы.
Критически важно понимать, что макет печатной формы в 1С (часто представленный в формате MXL) структурирован по именованным областям. Для корректного получения итогов агрегатные функции должны быть помещены в соответствующую область. Рассмотрим основные типы областей для табличных частей:
[Товары.Наименование], [Товары.Количество]. Если агрегатные функции, такие как СуммаПоКолонке([Товары.Сумма]), помещены в эту область, они будут вычислены для каждой отдельной строки, что приводит к ошибочному повторению итога на каждой строке.Для правильной работы нам необходимо обеспечить, чтобы агрегатные функции находились именно в области "Подвала" или "Итогов", которая обрабатывается после всех строк.
Один из пользователей нашел и поделился рабочими примерами для различных агрегатных функций, которые позволяют получить нужные итоги по табличной части. Эти выражения следует размещать в области "Подвал" или "Итоги" табличной части макета.
[КоличествоСтрок([Товары.Количество])] // Общее количество строк в табличной части
[МаксимумПоКолонке([Товары.Цена])] // Максимальное значение в колонке "Цена"
[МинимумПоКолонке([Товары.Количество])] // Минимальное значение в колонке "Количество"
[СреднееПоКолонке([Товары.Количество])] // Среднее значение в колонке "Количество"
[СуммаПоКолонке([Товары.Сумма])] // Сумма значений в колонке "Сумма"
Обратите внимание на синтаксис: квадратные скобки [] используются для обозначения выражений, а имя табличной части (например, Товары) указывается внутри функции перед именем колонки.
Более сложная, но часто встречающаяся задача — это получение суммы по колонке, которая сама является результатом какого-либо вычисления. Например, требуется вычислить общую длительность работ, если в табличной части есть поля Начало и Окончание. Формула для одной строки может выглядеть так: ([Исполнители работ.Окончание] - [Исполнители работ.Начало]) / 3600 (для перевода секунд в часы). Как же просуммировать такие вычисляемые значения?
Мы рассмотрим несколько подходов к решению этой задачи.
Это наиболее рекомендуемый и надежный способ. Суть его заключается в том, что вы добавляете новый реквизит в табличную часть документа, который будет хранить уже рассчитанное значение.
ИсполнителиРабот), добавьте новый реквизит, например, ДлительностьВЧасах, с типом "Число".ДлительностьВЧасах при изменении полей Начало или Окончание в соответствующей строке табличной части.
// Пример кода в модуле формы документа (или объекта)
// Для табличной части "ИсполнителиРабот"
&НаСервере
Процедура ИсполнителиРаботНачалоПриИзменении(Элемент)
// Вычисляем длительность при изменении поля Начало
РассчитатьДлительностьСтроки(Элемент.ТекущиеДанные);
КонецПроцедуры
&НаСервере
Процедура ИсполнителиРаботОкончаниеПриИзменении(Элемент)
// Вычисляем длительность при изменении поля Окончание
РассчитатьДлительностьСтроки(Элемент.ТекущиеДанные);
КонецПроцедуры
&НаСервере
Процедура РассчитатьДлительностьСтроки(СтрокаТабличнойЧасти)
Если СтрокаТабличнойЧасти.Начало <> Неопределено И СтрокаТабличнойЧасти.Окончание <> Неопределено Тогда
Длительность = СтрокаТабличнойЧасти.Окончание - СтрокаТабличнойЧасти.Начало; // Разность в секундах
СтрокаТабличнойЧасти.ДлительностьВЧасах = Длительность / 3600;
Иначе
СтрокаТабличнойЧасти.ДлительностьВЧасах = 0;
КонецЕсли;
КонецПроцедуры
ДлительностьВЧасах будет заполняться, вы сможете легко получить его сумму в шаблоне, используя уже знакомую нам функцию в области "Подвал" или "Итоги":
[СуммаПоКолонке([ИсполнителиРабот.ДлительностьВЧасах])]
Этот метод обеспечивает высокую производительность, так как вычисление происходит один раз при изменении данных, а не каждый раз при формировании отчета.
В некоторых случаях, особенно на более новых версиях платформы 1С:Предприятие 8.3, система может позволять использовать достаточно сложные выражения непосредственно внутри агрегатной функции. Однако это не гарантируется и сильно зависит от конкретной версии платформы и используемого механизма построения отчетов или шаблонов.
Если бы такая возможность существовала, гипотетическая запись могла бы выглядеть так:
[СуммаПоКолонке(([ИсполнителиРабот.Окончание] - [ИсполнителиРабот.Начало]) / 3600)]
Тем не менее, мы рекомендуем избегать этого подхода, если нет точной уверенности в его работоспособности, и использовать более надежный метод с добавлением отдельного реквизита.
Если первые два метода по каким-то причинам не подходят, можно выполнить расчет итоговой суммы в коде модуля объекта или модуля менеджера документа, а затем передать уже готовое значение в шаблон как отдельный параметр.
// Пример кода в модуле объекта документа или в процедуре формирования печатной формы
ОбщаяДлительностьВЧасах = 0;
Для Каждого СтрокаРабот Из ЭтотОбъект.ИсполнителиРабот Цикл
Если СтрокаРабот.Начало <> Неопределено И СтрокаРабот.Окончание <> Неопределено Тогда
Длительность = СтрокаРабот.Окончание - СтрокаРабот.Начало; // Разность в секундах
ОбщаяДлительностьВЧасах = ОбщаяДлительностьВЧасах + (Длительность / 3600);
КонецЕсли;
КонецЦикла;
// Далее передаем ОбщаяДлительностьВЧасах в шаблон как параметр.
// Например, если вы формируете через Макет.Область.Параметры.Вставить("ИтогДлительности", ОбщаяДлительностьВЧасах);
[ИтогДлительности]
Этот метод гибок и позволяет выполнять любые сложные вычисления, но требует большего объема кодирования и передачи данных из кода в макет.
Правильное использование агрегатных функций в шаблонах 1С требует понимания структуры макета и корректного размещения выражений в соответствующих областях. Для простых итогов используйте функции типа СуммаПоКолонке в области "Подвал". Для вычисляемых колонок самым надежным способом является добавление дополнительного реквизита в табличную часть, который будет хранить промежуточный результат. Используя эти подходы, вы сможете эффективно создавать печатные формы с полными и корректными итогами.