Приветствую Вас Гость | RSS

Delphi заготовки

Воскресенье, 12.05.2024, 17:45
Главная » Файлы » Мои файлы

FastReport Печать суммы по группе в заголовке
25.06.2012, 08:00


Печать итоговой суммы по группе в заголовке группы.

Этот довольно часто используемый прием требует использования скрипта. Ведь в обычном отчете значение суммы становится доступным только после того, как будут обработаны все записи группы. Чтобы вывести сумму в заголовке группы (т.е. до того, как будет обработана группа), используется следующий алгоритм:

- отчет делается двухпроходным;

- на первом проходе считается сумма по каждой группе и сохраняется в каком-нибудь массиве;

- на втором проходе значения извлекаются из массива и печатаются в заголовке группы.

Продемонстрируем, как решить эту задачу двумя способами. Для начала создадим новый проект в Delphi, на форму положим компоненты TQuery, TfrxReport, TfrxDBDataSet. Настроим их следующим образом:

Query1:

DatabaseName = 'DBDEMOS'

SQL =

 select * from customer, orders where orders.CustNo = customer.CustNo

 order by customer.CustNo, orders.OrderNo frxDBDataSet1:

DataSet = Query1

 UserName = 'Group'

Зайдем в дизайнер и подключим наш источник данных к отчету. В настройках отчета (пункт меню "Отчет | Настройки") включим двойной проход. Добавим в отчет два бэнда: "Заголовок группы" и "Данные 1 уровня". В редакторе бэнда "Заголовок группы" укажем условие – поле данных Group.CustNo. Дата-бэнд привяжем к источнику данных Group и разместим объекты следующим образом:

frum_339

Выделенный на рисунке объект (его имя – Memo8) мы используем для вывода суммы.

Способ 1.

Мы используем в качестве массива для хранения сумм класс TStringList. Значения будем хранить в виде строк. При этом первая строка в списке будет соответствовать значению первой группы, и т.д. Для подсчета номера группы будет использована целочисленная переменная, которую мы будем увеличивать после печати очередной группы.

Итак, наш скрипт будет выглядеть следующим образом:

         var

          List: TStringList;

          i: Integer;

  procedure frReport1OnStartReport(Sender: TfrxComponent);

  begin

     List := TStringList.Create;

  end;

  procedure frReport1OnStopReport(Sender: TfrxComponent);

  begin

     List.Free;

  end;

 

    procedure Page1OnBeforePrint(Sender: TfrxComponent);

    begin

      i := 0;

    end;

 

    procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);

    begin if Engine.FinalPass then

     Memo8.Text := 'Sum: ' + List[i];

    end;

   procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);

    begin

       List.Add(FloatToStr(<SUM(<Group."ItemsTotal">,MasterData1)>));

            Inc(i);

    end;

 

   begin

   end.

По именам процедур можно видеть, какие события мы использовали:

 

Report.OnStartReport, Report.OnStopReport, Page1.OnBeforePrint, GroupHeader1.OnBeforePrint, GroupFooter1.OnBeforePrint. Что касается первых двух событий, то они, как уже говорилось, вызываются в начале и в конце отчета, соответственно. Чтобы создать обработчики для этих событий, надо выделить объект "Отчет" в окне "Дерево отчета" – его свойства появятся в инспекторе объектов. Далее действуем стандартным образом – переключаемся на закладку "События" инспектора и создаем обработчики.

Почему мы не воспользовались для создания списка List главной процедурой, а сделали это в событии OnStartReport? Потому, что созданный объект надо после завершения отчета освободить. Поэтому логично создавать объекты в событии OnStartReport, а освобождать их в OnStopReport. В других случаях (когда не нужно освобождать память) можно пользоваться главной процедурой для инициализации переменных.

С созданием и освобождением объекта List все понятно. Теперь рассмотрим, как работает скрипт. В начале страницы счетчик текущей группы (переменная i) сбрасывается в 0 и увеличивается на единицу после печати каждой группы (в событии GroupFooter1.OnBeforePrint). В этом же событии в список добавляется вычисленное значение суммы. Событие GroupHeader1.OnBeforePrint на первом проходе не срабатывает (проверка Engine.FinalPass). На втором проходе (когда список List заполнен значениями), в этом событии извлекается значение, соответствующее текущей группе, и записывается в текст объекта Memo8, который и показывает сумму в заголовке группы. В готовом отчете это выглядит так:

frum_340

Как видим, алгоритм достаточно простой. Но и его можно упростить.

Способ 2.

Мы используем в качестве массива для хранения сумм список переменных отчета. Как мы помним, обращение к таким переменным осуществляется с помощью функций Get и Set. Это избавит нас от необходимости создавать лишние объекты и освобождать память. Наш скрипт будет следующим:

       procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);

       begin

         if Engine.FinalPass then memo8.Text := 'Sum: ' + Get(<Group."CustNo">);

       end;

            procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);           

       begin

                    Set(<Group."CustNo">,FloatToStr(<SUM(<Group."ItemsTotal">,MasterData1)>)); 

       end;

           Begin

      end.

Как видно, скрипт значительно упростился. Код в обработчике GroupFooter1.OnBeforePrint устанавливает значение переменной с именем, равным номеру клиента (можно использовать любой идентификатор, однозначно идентифицирующий клиента, например его имя <Group."Company">). Если такой переменной нет – она создается, если есть – меняется ее значение. В обработчике GroupHeader1.OnBeforePrint извлекается значение переменной с номером текущей группы.

Категория: Мои файлы | Добавил: NetSoftWare
Просмотров: 3793 | Загрузок: 0 | Комментарии: 1 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *: