Группировки в FastReport

В продолжение темы практического использования компонентов FastReport в бухгалтерском программном комплексе расчета с покупателями, я покажу несколько практических примеров использования группировок. Для примера я использую тот же реестр полученных оплат, который описан в первой статье “Наследование в Fast Report”
Напомню, что упрощенный вид таблицы такой:

  • Синтетический ключ (PK)
  • Расчетный период
  • Код плательщика
  • Наименование плательщика
  • Вид оплаты (FK)
  • Платежный документ (FK)
  • Дата оплаты
  • Сумма оплаты
  • Вид услуги (FK)

 

Среди прочих отчетов заказчик хочет иметь список платежей за период, при этом, чтобы у пользователя была возможность заказать группировку по видам оплат, по видам платежных документов, по видам оплат и документов, и наконец, совсем без группировки. (На самом деле требуется больше параметров для заказа, но для описания технологии работы другие параметры не важны.) Заголовок и столбцы всех 4-х отчетов одинаковые, поэтому нам понадобится один шаблон отчета с двумя группами. Этими группами мы и будем управлять.

Для создания отчета “Список платежей” нажимаем меню “файл”-“новый…”, переходим на закладку Шаблоны и выбираем базового отчет BaseReport (его создание описано в первой статье) и устанавливаем флажок “Наследовать отчет“. В получившемся отчете уже есть одна наследованном группа — она будет группировать по видам платежей. Добавим еще одну группу для платежных документов. Вторая группа будет сразу по умолчанию добавлена внутрь первой. При необходимости группы можно поменять местами, перетаскивая мышкой вторую группы выше первой, но для нашего отчета этого делать не надо.

Также согласно документации (UserManual-ru, гл 3.1) обязательным требованием для отчета с группировками является SQL запрос с сортировкой по группируемым полям.

Готовый отчет имеет следующий вид:

На форме заказа отчета два флажка “группировать по видам оплат”, “группировать по платежным документам” которые работают независимо друг от друга.

Включение/выключение видимости заголовков и подвалов групп выполняется с помощью свойства Visible. Методом FMainReport.FindObject находим указатель на заголовок группы и устанавливаем его свойство Visible в соответствии с флажком на форме заказа. То же делаем и с подвалом группы. Затем изменяем строку ORDER BY в SQL запросе. Если пользователь установил только флажок “вид оплаты”, то сортировка должна начинаться с поля “вид оплаты”, если установил только флажок “платежный документ”, то с поля “платежный документ”, а если установил оба флажка — то необходима сортировка по обоим полям.

При работе с вложенными группами может возникнуть необходимость исключить из запроса поле (например, при использовании GROUP BY), по которому выполняется одна из группировок в отчете. Например, заказчика интересует общая сумма оплаты каждого абонента в день по видам платежей. Тогда необходимо группировать по дате оплаты абонента, чтобы в итоге получить одну строку, если у абонента больше чем один платеж в день.

В этом случае для выключения группировки не достаточно присвоить False свойству Visible. Если такой отчет запустить то получим ошибку:

Установка свойства Visible:= False не отменяет выполнение выражения записанного в свойстве Condition, а там есть обращение к несуществующему в запросе полю. Ошибка исчезнет если свойству Condition присвоить значение какой-нибудь константы, например 1.

Для повышения эксплуатационных качеств отчета используем еще одну особенность FastReport — динамические группы. Наши заказчики уже успели оценить удобство такой интерактивности отчетов, то есть когда группа открывается/закрывается от щелчка мыши на заголовке группы в окне предварительного просмотра.

Основная проблема при использовании динамических групп возникает при вычислении суммы по группе. Я использую несколько вариантов вычисления суммы:

  1. Самый простой вариант. Ничего не менять ни у заголовка, ни у подвала динамической группы, в этом случае при сворачивании будет виден и заголовок и подвал. В работе я практически не использую этот вариант, так как наглядность такого отчета, на мой взгляд, низкая.

  2. Самый правильный вариант. Сумма по группе печатается в заголовке группы. В этом случае, если не предпринять дополнительных действий, то при запуске отчета сумма будет равна 0. Выхода два — создать специальный запрос для вычисления суммы или выполнять отчет в два прохода, то есть установить свойство frxMainReport.ExgineOptions.DoublePass = True. В любом случае для этого варианта необходимо изменить шаблон отчета. Подвал группы убрать (Visible:= False), а сумму поместить в заголовок группы.
    Я столкнулась с тем, что конечные пользователи у заказчика не всегда согласны видеть сумму впереди группы, поэтому появился третий вариант.
  3. Не самый красивый вариант, но, как не странно, именно он больше всего устраивает конечных пользователей. При сворачивании группы в подвале группы надо скрыть метку “Итого по группе”.
 procedure grMainFooterOnBeforePrint(Sender: TfrxComponent);
begin
if mdMainDetail.Visible then
Memo16.Text := ' Итого по '+ frxMainDBDataset."NAME_FULL"
else
Memo16.Text := '';
end;

Такой отчет будет иметь следующий вид (при свернутых группах):

  1. При таком варианте возникает проблема с суммой по группе. Если сумму считать обычным способом SUM(frxMainDBDataset.”PL_SUMMA”), то при запуске значение будет равно 0. Для того чтобы посчитать сумму в свернутой группе, необходимо написать следующее SUM(frxMainDBDataset.”PL_SUMMA”, mdMainDetail, 1), где 1 – учитывать невидимый бэнд mdMainDetail.
  2. Самый сложный вариант. Это комбинация 2 и 3, т.е. когда при открытой группе будет показана сумма в подвале и спрятана в заголовке, а при закрытой группе подвал полностью спрятан и показана сумма в заголовке. В моей практике всегда хватало использования варианта 3.

Использование групп очень удобно и гибко, так как число уровней вложенностей не ограниченно. Это позволяет при помощи ПРОСТОГО управления группами на одном отчете построить несколько близких по виду отчетов.

Copyright© 2007 Ирина Цыбульникова  Специально для Delphi Plus

Comments are closed.