Думки по поводу формирования текса.

Отчёт

Результат

В хранилище организуем список объектов, которые будут содержать ссылку на формулу для подсчёта агрегатных функций и привязываем их к изменению бенда. При получении новой строки бенда, пересчитываем переменную.


Сами думки:


В процессе подготовки(prepare()) m_memo->part() получил "формулу" и разобрал её.

В процессе формирования отчёта имена переменных должны быть заменены значениями и произведено "вычисление", т.е. сформирован текст для отображения.

Не все данные (значение переменных) готовы при первом проходе, например агригатные фунции (sum) или количество страниц в отчёте.

Итак...

  1. Для каждого memoFix необходим свой набор данных, некоторые из которых можно получить и при первом проходе, а некоторые только при втором.
  2. Желательно при первом проходе сократить "формулу", оставив только переменные которые невозможно определить сразу.

Для примера рассмотрим выражение:

(5 + P1 * P2) / SUM(P3), где Pi - данные запросов и/или другие переменные данные.

Возможны два варианта:

  1. Формула остаётся в memo, а для каждого memoFix, создаём полный список переменных из формулы. "Локальные" переменные (которые можно определить сразу) определяются сразу и принадлежат объекту memoFix. "Глобальные" создаются в "хранилище данных" (DataStorage) и обрабатываются им.
    Внимание вопрос!
    может список сделать на этапе подготовки?

    В данном сучае нам необходимо завести две переменных P1, P2 для каждого memoFix и "попросить" хранилище вычислить сумму по P3.


  2. При первом проходе "схлопнуть" фомулу. Видоизмененную формулу сохраняем в мемо, и уже для неё создаём необходимые переменные в memoFix.

    Используя этот подход, можно при первом проходе вычислить "скобку". Соответсвенно можно завести переменную для скобки и переменную в хранилице.


Проблемы агрегатных функций.


SUM() MAX() MIN() AVG() COUNT()

"Вычислитель":

  1. не знает когда меняется "срока" в наборе данных и не может, в это время, производить необходимые вычисления.
  2. в выражение могут входить данные не из текущего бенда - когда вычислять?

"Хранилище данных":

  1. не умеет вычислять сложные выражения.
  2. в выражение могут входить данные из разных наборов данных - когда вычислять?


Хорошая мысля приходит опосля.... Смотрим FastReport (см. ниже...).

Т.е. агрегатные функции привязаны не к набору данных а к бенду. Так как параметром функции может оказаться выражение содержащее данные из нескольких наборов данных, этот подход позволяет избежать неопределённости. По умолчанию - бенд текущий.




Агрегатные функции FastReport (кратко).

       В большинстве случаев в групповых отчетах надо выводить некую итоговую информацию: сумма по группе, количество элементов группы и т.п. В FastReport для этих целей существуют так называемые агрегатные функции. С их помощью можно подсчитать функцию от определенного значения по диапазону данных.

    Синтаксис всех агрегатных функций (за исключением COUNT) следующий (рассмотрим на примере ф-и SUM):

 SUM(expression, band, flags)

SUM(expression, band)

SUM(expression)

        Назначение параметров следующее:

 expression – выражение, значение которого необходимо обработать

band – имя дата-бэнда, по которому будет идти обработка

flags – битовое поле, которое может содержать следующие значения и их комбинации:

       1 – учитывать невидимые бэнды

       2 – накапливать значение (не сбрасывать при очередном выводе)

 

       Как видно, обязательным параметром является только expression, остальные при вызове функции могут быть опущены. Тем не менее, рекомендуется всегда использовать параметр band, это позволит избежать ошибок.

 

       Функция COUNT имеет следующий синтаксис:

 COUNT(band, flags)

COUNT(band)

 

       Назначение параметров аналогично вышеописанным.

 

       Существует общее для всех агрегатных функций правило: функция может быть подсчитана только для дата-бэнда и выведена только в бэнде-подвале (к последним относятся бэнды: подвал, подвал страницы, подвал группы, подвал колонки, подвал отчета).

 

       Как работают агрегатные функции? Рассмотрим это на примере нашего отчета с группами. Добавим в отчет новые элементы:

 

       Итак, каков принцип работы агрегатных функций? Перед построением отчета FastReport сканирует содержимое объектов "Текст" с целью нахождения агрегатных функций. Найденные функции привязываются к соответствующим дата-бэндам (в нашем примере функция SUM привязывается к бэнду MasterData1). При построении отчета, когда дата-бэнд выводится на экран, подсчитывается значение связанных с ним агрегатных функций. В нашем случае накапливается сумма значений поля Group."ItemsTotal". После вывода подвала группы, в котором отображается накопленное значение агрегатной функции, значение функции сбрасывается и цикл повторяется для следующих групп.

 

       Здесь можно пояснить назначение параметра flags в агрегатных функциях. В некоторых отчетах часть дата-бэндов (или все) могут быть скрыты, однако нам все равно может понадобиться посчитать значение агрегатной функции с учетом всех дата-бэндов. Так, в нашем примере можно отключить свойство Visible у дата-бэнда, после этого он перестанет выводиться на экран. Чтобы подсчитать сумму по скрытым дата-бэндам, добавим третий параметр в вызов функции:

 

       Значение параметра flags = 2 позволяет не сбрасывать накопленное значение функции после ее вывода. Это позволяет печатать так называемые нарастающие итоги. Модифицируем вызов функции: