Агрегатные функции можно рассчитывать в целом по источнику данных, по бэнду, по группе или по странице. При расчете агрегатной функции по странице в некоторых случаях значение может быть неправильным. В этой статье мы опишем причины возникновения ошибки и пути ее решения. Для упрощения объяснений далее мы будем говорить только про функцию суммирования, имея в виду все агрегатные функции.
Процесс суммирования значений по странице
Суммирование значений по странице отчета происходит только после полного построения отчета, поэтому должно быть точным. Но движок генератора отчетов суммирует значения не из текстовых компонентов, так как в них записываются чаще всего уже округленные значения. Движок ищет на странице все построенные бэнды с данными. В каждом бэнде Данные хранится позиция источника данных на момент рендеринга этого бэнда. И движок суммирует именно исходные значения из источника данных.Почему возникает ошибка расчета функции
Если у датабэнда выставлено свойствоCanBreak=false, то каждая строка датабэнда рендерится целым контейнером, который не разбивается на части. Если он не помещается на текущей странице, то переносится на следующую страницу целиком. Поэтому каждая строка датабэнда есть только в единственном экземпляре, и все расчеты получаются правильными.Но если у датабэнда установлено свойство
CanBreak=true, то строка датабэнда, если она не помещается на странице целиком, может разбиваться на части. Одна часть бэнда остается на текущей странице, другая переносится на следующую страницу. Компоненты этого бэнда в зависимости от размеров и расположения могут попасть в разные части это бэнда. А если и у них включено CanBreak=true, то и сами компоненты могут быть разбиты на части.И вот тут возникает вопрос: если текстбокс разбит на части, на какой странице учитывать его значение?
Наша команда пыталась написать умный алгоритм, который бы анализировал такие ситуации. Но в нашем продукте можно сделать отчеты с такой сложной структурой, что учесть все нюансы просто невозможно. Поэтому уже давно было принято следующее решение:
- если после разбиения бэнда в первой части, то есть, внизу страницы, остается хотя бы один компонент, то при суммировании он учитывается только на этой странице;
- если все компоненты бэнда переносятся на верхнюю часть следующей страницы, то, соответственно, его значения учитываются при суммировании только на следующей странице.
В большинстве случаев это срабатывает корректно.
Пример проблемы
Разберем частный случай учета значений текстовых компонентов при суммировании по странице.Исходные условия: у бэндов Данные установлено
CanBreak=true, то есть содержимое разбивается на части. У всех текстовых компонентов на бэнде значение CanShrink=true. Это означает, что все текстовые компоненты без данных сворачиваются и имеют нулевую высоту.При разбиении бэнда эти текстовые компоненты остаются на предыдущей странице, а все компоненты с данными переносятся на следующую страницу. То есть, первая часть бэнда оказывается не пустая, и поэтому значение с этого бэнда учитывается только на предыдущей странице.
Варианты решения проблемы
Самый простой способ – установитьCanBreak=falsе для бэнда Данные. Это и решит проблему с ошибкой суммирования, и ускорит построение отчета.Если CanBreak по какой-то причине использовать нельзя, можно установить для текстовых компонентов свойство
GrowToHeight=true.В общем случае рекомендуется делать оба этих действия, так как установка GrowToHeight также помогает избежать некоторых проблем при последующих экспортах.