Формирование сложного отчёта
Добрый день! Кто знает, как формировать сложный отчёт?
Вот, что нужно сделать:
На одной странице расположены три таблицы. Причём первая таблица слева в первой области страницы (вверху), вторая таблица справа во второй области страницы (посередине), третья слева в третьей области страницы (внизу).
По образцу Таблица № 1 содержит 5 нарисованных строчек, Таблица № 2 содержит 7 строчек, таблица № 3 содержит 5 строчек.
И выводятся данные в эти таблицы. Фактически оказалось, что таблица № 1 содержит 8 строчек данных, таблица № 3 содержит 6 строчек данных.
Требуется, если получается переполнение строчек таблицы, создать копию страницы с такими же таблицами и с таким расположением, где в таблице № 1 выводятся 3 строчки (8-5), таблица №2 пустая будет, в таблице № 3 будет 1 строчка.
И как это можно сделать? Даже если при переполнении таблицы № 1 на страничке ещё операция вывода данных в таблицу № 3 на первом оригинальном листе ещё не закончилась.
Легко мне сделать, когда отчёт Master-Detail или опцию в Band'е Stretched ставить = true (чтобы была видна полностью информация в строке-регулировка строки по высоте).
Запрещено при переполнении таблицы № 1 свдигать вниз перерисовку (вывод) таблиц № 2 и № 3, а также остальной части отчёта.. Только создание копии той же страницы (страницы не нумеруются) и выводятся на новой недостающие записи. FastReport нормальные учебники не пишет, его хелп сырой.. и скудный к тому..
Вот, что нужно сделать:
На одной странице расположены три таблицы. Причём первая таблица слева в первой области страницы (вверху), вторая таблица справа во второй области страницы (посередине), третья слева в третьей области страницы (внизу).
По образцу Таблица № 1 содержит 5 нарисованных строчек, Таблица № 2 содержит 7 строчек, таблица № 3 содержит 5 строчек.
И выводятся данные в эти таблицы. Фактически оказалось, что таблица № 1 содержит 8 строчек данных, таблица № 3 содержит 6 строчек данных.
Требуется, если получается переполнение строчек таблицы, создать копию страницы с такими же таблицами и с таким расположением, где в таблице № 1 выводятся 3 строчки (8-5), таблица №2 пустая будет, в таблице № 3 будет 1 строчка.
И как это можно сделать? Даже если при переполнении таблицы № 1 на страничке ещё операция вывода данных в таблицу № 3 на первом оригинальном листе ещё не закончилась.
Легко мне сделать, когда отчёт Master-Detail или опцию в Band'е Stretched ставить = true (чтобы была видна полностью информация в строке-регулировка строки по высоте).
Запрещено при переполнении таблицы № 1 свдигать вниз перерисовку (вывод) таблиц № 2 и № 3, а также остальной части отчёта.. Только создание копии той же страницы (страницы не нумеруются) и выводятся на новой недостающие записи. FastReport нормальные учебники не пишет, его хелп сырой.. и скудный к тому..
Комментарии
Тут тебе хелп не поможет...
Можна попробовать сделать так:
Перед выводом на печать данные табличек загнать в массив, по ходу определяя, есть ли необходимость в формировании второй страницы. Печатную форму положить на чайлд, растнянутый на всю страницу. А затем, например, из сумари вызывать ентот самый чайлд стоко раз скоко нада, переопределяя переменные массива.
Немного через ж... посмотрим, может кто что получше предложит
Я их попросил написать поподробней, как это сделать?
Band Child положить на главную страничку. затем на Band Child SubReport. Но надо как то родительский бенд положить, иначе содержимое Band Childа не выведётся. И что за бенд этот? Не Master Header, Master Data. А как контроллировать вывод строго по N-записям?
Причём две или несколько таблиц могут распологаться в одной области, например, в середине полосы,
в нижней части, в верхней части. И причём размеры таблиц на этой странице отчёта фиксированные.
Если данные не влезают в эти фиксированные таблицы, то сами эти же таблицы печатаются пустыми,
и кроме того создаются ещё дополнительные новые странички, на которых выводятся эти таблицы
в другом произвольном формате, чтобы была возможность показать все данные.
Как создать сложный отчёт?
//=======================================================================
1. На страницу бросают компонент TfrSubReportView и растягивают его под размер фиксированной таблицы.
Примечание: на одной странице в одной области могут быть несколько компонентов SubReport1,
SubReport2,... и они могут пересекаться.
Первый шаг используется, если 2 и более таблицы лежат на одной полосе или в одном ряду.
Этот шаг можно пропустить, если выводимые таблицы не лежат рядом по горизонтали.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2. На странице Page или на странице вложенного отчёта SubReport ложим следующие компоненты:
2.1 - бэнд Master Data (TfrBandView) с названием vmDataTable1.
Выбираем DataSet : Виртуальный с количеством записей = 1
Ставим свойство Height := 0
2.2 - бэнд Master Footer (TfrBandView) с названием vmFooterTable1. Ставим свойство Height := 10-13
2.3 - бэнд Master Header (TfrBandView) с названием mHeaderTable1. Ставим свойство Height := 0
2.4 - бэнд Child (TfrBandView) с названием cHeaderTable1.
2.5 - бэнд Master Data (TfrBandView) с названием mDataTable1
Выбираем нужный DataSet (не виртуальный, а реальный)
2.6 - бэнд Child (TfrBandView) с названием cEmptyRowTable1.
Высота компонента cEmptyRowTable1 = высоте компонента mDataTable1
2.7 - бэнд Master Footer (TfrBandView) с названием mFooterTable1. Ставим свойство Height := 10-13
Два бэнда vmDataTable1 и vmFooterTable1 являются виртуальной таблицей. Когда данных нет, и все равно надо рисовать
фиктивную таблицу с заданным количеством строк. Чтобы каждый раз не дублировать заголовки таблицы, используется
общий компонент (для фиктивной и для реальной таблицы) - cHeaderTable1.
Когда данных мало выводится, а до нижней границы таблицы недостаёт несколько строчек. И их надо нарисовать,
вот для этого используется компонент cEmptyRowTable1 - дорисовка недостающих строчек.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3. Для компонента vmDataTable1 указываем дочерний компонент cHeaderTable1.
Свойство vmDataTable1.Child = cHeaderTable1.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4. Для компонента mHeaderTable1 указываем дочерний компонент cHeaderTable1.
Свойство mHeaderTable1.Child = cHeaderTable1.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5. На компоненте cHeaderTable1 рисуем заголовок таблицы.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6. На компонент mDataTable1 кладём столько TfrMemoView сколько надо, и указываем данные.
Например, [DialogForm.qLicFounders."TOR_ID_DICT"]
Для каждого компонента TfrMemoView можно указывать свойства:WordWrap (перенос слов) : true, Stretched (растягиваемый) :
true
и для самого компонента mDataTable1 указываем свойство:Stretched (растягиваемый) : true
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7. На компонент cEmptyRowTable1 кладём столько TfrMemoView сколько на mDataTable1, и НЕ указываем данные.
То есть оставляем их пустыми.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8. На двух компонентах vmFooterTable1 и mFooterTable1 ложим (рисуем) линию нижней рамки таблицы.
Всё, ура. таблица нарисована и готова. Это таблица, которая работает в двух режимах: рисование фиктивной таблицы (когда
данных нет) и рисование таблицы со всеми данными и с недостающими строчками. Нет переполнения таблицы.
А когда таблица переполнена, то создаётся новая страничка и на ней рисуется та самая копия таблицы.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9. Создаём ещё одну страницу. Запоминаем номер страницы. И просим её больше не передвигать.
На неё кладём всего три компонента.
9.1 - бэнд Master Header (TfrBandView) с названием по умолчанию - MasterHeader1. Свойство Height поставить равным, сколько
требуется для заголовка таблицы. То есть высота равна высоте компонента cHeaderTable1 на другой странице
9.2 - бэнд Master Data (TfrBandView) с названием по умолчанию - MasterData1.
Выбираем нужный DataSet (не виртуальный, а реальный)
9.3 - бэнд Master Data (TfrBandView) с названием по умолчанию - MasterFooter1.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10. На компоненте MasterHeader1 рисуем заголовок таблицы.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11. На компонент MasterData1 кладём столько TfrMemoView сколько надо, и указываем данные.
Например, [DialogForm.qLicFounders."TOR_ID_DICT"]
Для каждого компонента TfrMemoView можно указывать свойства:WordWrap (перенос слов) : true, Stretched (растягиваемый) :
true
и для самого компонента mDataTable1 указываем свойство:Stretched (растягиваемый) : true
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12. На компоненте MasterFooter1 ложим (рисуем) линию нижней рамки таблицы.
Таблица уже готова.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13. В тексте обработчика vmFooterTable1.OnBeforePrint пишем:
begin
//Выводим пустые строчки
for i:=0 to 4 do //Здесь может быть больше или меньше строк
ShowBand(cEmptyRowTable1);
end
Комментарий: Это когда данных нет, и все равно надо рисовать фиктивную таблицу
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14. В тексте обработчика mHeaderTable1.OnBeforePrint пишем:
begin
{
Здесь FinalPass означает второй проход. И во втором проходе проверяем условие.
Если окажется, что высота таблицы больше высоты странички, то создаём новую
страничку-вкладку.
}
Page2.Visible := false; //Это и есть наша созданная и запомненная страничка
//Если идёт второй проход
if FinalPass then
begin
if nTable1Height < nFactTab1Height then
begin
//Создаём новую страничку и на ней рисуем ту же самую фиктивную таблицу с данными
Page2.Visible := true;
end;
end
else
//Первый проход
begin
//Будем считать общую высоту таблицы
//Сначала приравниваем высоту заголовка таблицы
nFactTab1Height := cHeaderTable1.Height;
end;
end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15. В тексте обработчика mDataTable1.OnBeforePrint пишем:
begin
if not FinalPass then
begin
if ([Line#] = 1) then
LastCurY := CurY
else
begin
if (CurY < LastCurY) then
LastCurY := 90;
//Будем считать общую высоту таблицы
nFactTab1Height := nFactTab1Height + (CurY - LastCurY);
LastCurY := CurY;
end;
end;
end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16. В тексте обработчика mFooterTable1.OnBeforePrint пишем:
begin
if not FinalPass then
begin
if (CurY < LastCurY) then
LastCurY := 90;
nFactTab1Height := nFactTab1Height + (CurY - LastCurY);
LastCurY := CurY;
end;
//Дорисовка недостающих строчек
if (nTable1Height >= nFactTab1Height) then
begin
//Определяем кол-во оставшихся мест-строчек
for i:=0 to Round ( ( nTable1Height - nFactTab1Height ) / cEmptyRowTable1.Height ) - 1 do
ShowBand(cEmptyRowTable1);
end;
end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17. В тексте обработчика Page1.OnBeforePrint пишем:
//Page1.OnBeforePrint
begin
//=== Таблица № 1. =============//
nTable1Height := SubRepTable1.Height;
Page2.Visible := false;
//Если идёт второй проход
if FinalPass then
begin
if (nTable1Height < nFactTab1Height) or (nFactTab1Height = 0) then
begin
//Рисуем пустую таблицу без данных
vmDataTable1.Visible := true;
vmFooterTable1.Visible := true;
mHeaderTable1.Visible := false;
mDataTable1.Visible := false;
mFooterTable1.Visible := false;
end
else
begin
vmDataTable1.Visible := false;
vmFooterTable1.Visible := false;
mHeaderTable1.Visible := true;
mDataTable1.Visible := true;
mFooterTable1.Visible := true;
end;
end
else
//Если идёт первый проход, и идёт инициализация переменной
nFactTab1Height := 0;
end;
//==========================================================
Всё отчёт готов, можете протестировать...