Формирование сложного отчёта

отредактировано 16:24 Раздел: FastReport 2.xx VCL
Добрый день! Кто знает, как формировать сложный отчёт?

Вот, что нужно сделать:

На одной странице расположены три таблицы. Причём первая таблица слева в первой области страницы (вверху), вторая таблица справа во второй области страницы (посередине), третья слева в третьей области страницы (внизу).
По образцу Таблица № 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 нормальные учебники не пишет, его хелп сырой.. и скудный к тому..

Комментарии

  • отредактировано 16:24
    Мда... Судя по всему бланк какой-то строжайшей отчетности ;)
    Тут тебе хелп не поможет...
    Можна попробовать сделать так:
    Перед выводом на печать данные табличек загнать в массив, по ходу определяя, есть ли необходимость в формировании второй страницы. Печатную форму положить на чайлд, растнянутый на всю страницу. А затем, например, из сумари вызывать ентот самый чайлд стоко раз скоко нада, переопределяя переменные массива.
    Немного через ж... посмотрим, может кто что получше предложит
  • отредактировано 16:24
    На другом форуме рекомендуют применять связку Band Child + SubReport

    Я их попросил написать поподробней, как это сделать?

    Band Child положить на главную страничку. затем на Band Child SubReport. Но надо как то родительский бенд положить, иначе содержимое Band Childа не выведётся. И что за бенд этот? Не Master Header, Master Data. А как контроллировать вывод строго по N-записям?
  • отредактировано 16:24
    Требуется создать сложный отчёт, при котором на одной странице размещаются более чем 1 таблиц.
    Причём две или несколько таблиц могут распологаться в одной области, например, в середине полосы,
    в нижней части, в верхней части. И причём размеры таблиц на этой странице отчёта фиксированные.
    Если данные не влезают в эти фиксированные таблицы, то сами эти же таблицы печатаются пустыми,
    и кроме того создаются ещё дополнительные новые странички, на которых выводятся эти таблицы
    в другом произвольном формате, чтобы была возможность показать все данные.
    Как создать сложный отчёт?
    //=======================================================================

    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;

    //==========================================================

    Всё отчёт готов, можете протестировать...

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.