Как устроена Галактика? - Отчет с итогами по странице.
Иногда возникают задачи, где нужно разработать отчет. Что бы на каждой странице этого отчета выводились итоги по странице. Чтобы в конце отчета выводились ито-ги по всему отчету в целом. Такие отчеты можно разрабатывать с помощью генера-тора отчетов 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 позволяет справиться с этой задачей.
Для примера рассмотрим отчет, к которому предъявляются следующие требования:
1) В отчет должна выводиться таблица с наименованиями товаров и суммами. Наименование товара может не уместится в одну строку текста, при этом высота строки таблицы должна автоматически увеличиваться, чтобы поместилось на-именование.
2) Для каждой страницы отчета нужно вывести итоги по странице цифрой и прописью.
3) Сумма итого по странице прописью также может не уместить в одну троку текста, при этом на листе под вывод итоговой суммы должно резервироваться ровно столько места, сколько для этого требуется.
4) Итоги по странице должны выводиться непосредственно после данных.
5) Отчет должен помещается на листе формата А4. Должны быть зарезервиро-ваны поля 1см сверху, снизу, слева и справа.
6) Заголовок таблицы должен повторяться на каждой странице.
7) На первой странице должен выводиться заголовок отчета с датой и названием организации.
8 ) На последней странице отчета, непосредственно после итогов по странице должны выводиться итоги по всему отчету цифрой и прописью.
9) Сумма итого по отчету прописью также может быть многострочной, при выводе на печать должно резервироваться достаточно места
10) Непосредственно после итогов по отчету, должны выводиться подписи ди-ректора главного бухгалтера и место для печати.
11) Если в конце последней страницы недостаточно места для вывода итогов по листу, итогов по отчету и подписей. То необходимо сформировать новую стра-ницу и перенести на нее заголовок таблицы и одну послюню строку с данными по товару.
Для реализации такого отчета можно предложить следующий метод или алгоритм:
1) На первом этапе определить общее количество строк таблицы и сосчитать итоговую сумму по всей ведомости.
2) Вторым шагом, определить, какую высоту займет текст с суммой итого по ве-домости. Текст для суммы можно получить с помощью функции FloatToWords. Высоту, которая необходима, для выдачи этого текса можно получить с помо-щью метода TfrxMemoView.CalcHeight (метод определен в базовом классе TfrxStretcheable)
3) Следующим этапом последовательно анализировать строки перед выводом в отчет. Определить высоту строки. Увеличить счетчик с итогом по странице и оп-ределить высоту для текста с итогом. С помощью тех же функций FloatToWords и TfrxMemoView.CalcHeight
4) Проверить умещается ли по высоте текущая строка вместе текущим стогом по странице на свободном месте страницы (метод Engine.FreeSpace). Если уме-щается, то вывести на печать текущую строку и перейти к обработке следующей строки. Если же текущая строка вместе с ее расчетным итогом уже не умещается на странице, то уменьшить сумму итога по станице на сумму текущей строки, вывести итог по предыдущей строке, дать генератору команду сформировать новую страницу, вывести на печать шапку таблицы и текущую строку.
5) Для последней строки ведомости в расчете занимаемого пространства (см пункт 3) учитывать также высоту итогов по всему отчету и высоту необходимую для вывода подписей.
6) Последний этап алгоритма, для последней страницы вывести на печать итоги и подписи.
Реализацию данного алгоритма проще всего поместить в обработчик события TfrxReportPage.OnManualBuild.
На мой взгляд, предложенный подход достаточно прост и понятен. Хотя это не единственно возможный вариант реализации. В примере задействована только не-большая часть возможностей FastReport.
Примечание: Основная трудность, которая возникла у меня при подготовке при-мера, в исследовании того как на самом деле работает функция TfrxMemoView.CalcHeight. К сожалению, эта функция не описана в документации. Как выяснилось в процессе тестирования отчета. Эта функция дает не правильный ре-зультат для полей отчета, значение которых определяется полем БД или выражением в тексте. Как выяснилось функция TfrxMemoView.CalcHeight корректно вычисляет высоту только для со статически заданным текстом. По этому если вы обратите вни-мание на исходный код примера - там везде применяется следующий прием:
- У расчетных объектов TfrxMemoView свойстово AllowExpressions="False"
- Расчет текста и его высоты полностью задан в скрипте
Код: Выделить всё
MemoName.text := <SUBTOTALDATASET."NAME">;
RatedFooterHeight := MemoName.CalcHeight;