Как устроена Галактика? – Отчет с итогами по странице

Иногда возникают задачи, где нужно разработать отчет. Что бы на каждой странице этого отчета выводились итоги по странице. Чтобы в конце отчета выводились итоги по всему отчету в целом. Такие отчеты можно разрабатывать с помощью генератора отчетов FastReport.
Требования к отчету в каждом конкретном случае могут отличаться. Для простых случаев вполне подойдет простой метод который описан в документации по FastReport. Метод состоит в том чтобы поместить агрегатную функцию SUM(expression, band, flags) на бэнды PageFooter -“Подвал страницы” и ReportSummary – “Подвал отчета”. Косметические поправки к оформлению, такие как “не отрывать PageFooter от данных”, можно корректировать с помощью не-сложных скрипов.

Например:

var
Y: extended;
procedure MasterData1OnAfterPrint(Sender: TfrxComponent);
begin
Y:=Engine.CurY;
end;
procedure PageFooter1OnBeforePrint(Sender: TfrxComponent);
begin
Engine.CurY:=Y;
end;

Этот метод хорошо подходит когда нужно вывести итоги просто цифрой, когда цифра с итогами уместится в одну строку фиксированной высоты, кода нет специальных требований к оформлению бланков строгой отчетности.

Однако в реальности отчеты могут быть более сложные. К оформлению таких отче-тов могут предъявляется различные дополнительные требования. Однако и в этих случаях FastReport позволяет справиться с этой задачей.

Для примера рассмотрим отчет к которому предъявляются следующие требования:

  • В отчет должна выводиться таблица с наименованиями товаров и суммами. Наименование товара может не уместится в одну строку текста, при этом высота строки таблицы должна автоматически увеличиваться, чтобы поместилось на-именование.
  • Для каждой страницы отчета нужно вывести итоги по странице цифрой и прописью.
  • Сумма итого по странице прописью также может не уместить в одну троку текста, при этом на листе под вывод итоговой суммы должно резервироваться ровно столько места, сколько для этого требуется.
  • Итоги по странице должны выводиться непосредственно после данных.
  • Отчет должен помещается на листе формата А4. Должны быть зарезервиро-ваны поля 1см сверху, снизу, слева и справа.
  • Заголовок таблицы должен повторяться на каждой странице.
  • На первой странице должен выводиться заголовок отчета с датой и названием организации.
  • На последней странице отчета, непосредственно после итогов по странице должны выводиться итоги по всему отчету цифрой и прописью.
  • Сумма итого по отчету прописью также может быть многострочной, при выво-де на печать должно резервироваться достаточно места
  • Непосредственно после итогов по отчету, должны выводиться подписи ди-ректора главного бухгалтера и место для печати.
  • Если в конце последней страницы недостаточно места для вывода итогов по листу, итогов по отчету и подписей. То необходимо сформировать новую стра-ницу и перенести на нее заголовок таблицы и одну послюню строку с данными по товару.

Для реализации такого отчета можно предложить следующий метод или алгоритм:

  • На первом этапе определить общее количество строк таблицы и сосчитать итоговую сумму по всей ведомости.
  • вторым шагом, определить, какую высоту займет текст с суммой итого по ве-домости. Текст для суммы можно получить с помощью функции FloatToWords. Высоту, которая необходима, для выдачи этого текса можно получить с помо-щью метода TfrxMemoView.CalcHeight (метод определен в базовом классе TfrxStretcheable)
  • Следующим этапом последовательно анализировать строки перед выводом в отчет. Определить высоту строки. Увеличить счетчик с итогом по странице и оп-ределить высоту для текста с итогом. С помощью тех же функций FloatToWords и TfrxMemoView.CalcHeight
  • Проверить умещается ли по высоте текущая строка вместе текущим стогом по странице на свободном месте страницы (метод Engine.FreeSpace). Если уме-щается, то вывести на печать текущую строку и перейти к обработке следующей строки. Если же текущая строка вместе с ее расчетным итогом уже не умещает-ся на странице, то уменьшить сумму итога по станице на сумму текущей строки, вывести итог по предыдущей строке, дать генератору команду сформировать новую страницу, вывести на печать шапку таблицы и текущую строку
  • Для последней строки ведомости в расчете занимаемого пространства (см пункт выше) учитывать также высоту итогов по всему отчету и высоту необходимую для вывода подписей.
  • Последний этап алгоритма, для последней страницы вывести на печать итоги и подписи.

Реализацию данного алгоритма проще всего поместить в обработчик события TfrxReportPage.OnManualBuild.

На мой взгляд, предложенный подход достаточно прост и понятен. Хотя это не един-ственно возможный вариант реализации. В примере задействована только небольшая часть возможностей FastReport.

Примечание: Основная трудность, которая возникла у меня при подготовке при-мера, в исследовании того как на самом деле работает функция TfrxMemoView.CalcHeight. К сожалению, эта функция не описана в документации. Как выяснилось в процессе тестирования отчета. Эта функция дает не правильный ре-зультат для полей отчета, значение которых определяется полем БД или выражени-ем в тексте. Как выяснилось функция TfrxMemoView.CalcHeight корректно вычисляет высоту только для со статически заданным текстом. По этому если вы обратите внимание на исходный код примера – там везде применяется следующий прием:

  • У расчетных объектов TfrxMemoView свойстово AllowExpressions=”False”
  • Расчет текста и его высоты полностью задан в скрипте
MemoName.text := <SUBTOTALDATASET."NAME">;
RatedFooterHeight := MemoName.CalcHeight;

пример проделанной работы (Acrobat Reader): Пример результата в формате Acobat
Исходники: Исходники примера и шаблон отчёта

Автор статьи: Михаил Ларин
Специально для reportingfor.info

Comments are closed.