вертикальный бэнд

отредактировано November 2009 Раздел: FastReport 4.0
привет!
вот возник такой вопрос, есть отчет с вертикальными бэндами, в бэнды надо выводить в ручную. Делаю через frxreportGetValue
CompareText(VarName, 'p1') = 0 then Value :=TableVals[frxUserDataSet1.RecNo+1,1];
Это понятно перемещаемся по вертикали, а как переместиться по горизонтали? MasterDetail2(вертикальный бэнд), как по нему перемещаться?

Вот еще вопросик, может как то решается следующая ситуация:
Есть отчет с переменным кол-вом строк и столбцов, делаем два датасета, один Master второй Detail(суммы по датам), но даты разные у каждой записи Master!
При выводе все смещается и получается каша! Вот пример
Как надо:
02.2009 | 03.2009 | 04.2009 | 05.2009
10 45 11
34 6

а выводится
02.2009 | 04.2009 | 05.2009 |
10 45 11
34 6


Помогите пожалуйста решить данный вопрос! А то то по вертикальным бэндам почти нет документации!

Комментарии

  • отредактировано 18:25
    У вас получается обыкновенная матрица.
    Т.е. RowInddex = Index div ColumnCount;
    написал:
    Вот еще вопросик, может как то решается следующая ситуация:
    Есть отчет с переменным кол-вом строк и столбцов, делаем два датасета, один Master второй Detail(суммы по датам), но даты разные у каждой записи Master!
    При выводе все смещается и получается каша! Вот пример
    Как надо:
    02.2009 | 03.2009 | 04.2009 | 05.2009
    10 45 11
    34 6
    Фильтровать датасет и скрывать все записи у которых нет дочерних.
  • отредактировано December 2009
    написал: »
    У вас получается обыкновенная матрица.
    Т.е. RowInddex = Index div ColumnCount;
    Фильтровать датасет и скрывать все записи у которых нет дочерних.

    Можно немного по подробнее, можно ли сделать это через DBDataset или ghbltncz UserDataset все таки!

    Я неправильно отобразил данные и Вы не так поняли, вот как надо
    Как надо:
    02.2009 | 03.2009 | 04.2009 | 05.2009|
    10 | 45 | | 11 |
    | 34 | 6 | |

    а выводится
    02.2009 | 04.2009 | 05.2009 |
    10 | 45 | 11 |
    34 | 6 | |
  • отредактировано 18:25
    ssvd написал: »
    Можно немного по подробнее, можно ли сделать это через DBDataset или ghbltncz UserDataset все таки!
    Подробнее не могу , ибо не знаю что в вашем конкретном случае значить "новая строка". Это могут быть данные из другого поля, либо данные с другим индексом или еще что-то.
    Выше я написал общую формулу определения индекса строки относительно глобального индекса(который можно считать в том же OnGetValue).
    ssvd написал: »
    Я неправильно отобразил данные и Вы не так поняли, вот как надо
    Как надо:
    02.2009 | 03.2009 | 04.2009 | 05.2009|
    10 | 45 | | 11 |
    | 34 | 6 | |

    а выводится
    02.2009 | 04.2009 | 05.2009 |
    10 | 45 | 11 |
    34 | 6 | |
    Тогда не понятна сама структура отчета.
    Можете показать конкретный отчет ?
  • отредактировано December 2009
    написал: »
    Подробнее не могу , ибо не знаю что в вашем конкретном случае значить "новая строка". Это могут быть данные из другого поля, либо данные с другим индексом или еще что-то.
    Выше я написал общую формулу определения индекса строки относительно глобального индекса(который можно считать в том же OnGetValue).
    Тогда не понятна сама структура отчета.
    Можете показать конкретный отчет ?

    вот файл отчета, к нему подключается два DBDateset соединенных как master-detail
    мастер - это строки, а детаил - это столбцы.
    допустим в мастер есть запись №1, в детаил на нее есть 4 записи с датами 03.2009,04.2009,05.2009,06.2009
    есть запись №2, в детаил на нее есть 2 записи с датами 03.2009,06.2009
    и тд.
    И когда формируется отчет то записи смещаются влево, то есть данные второй записи смещаются на столбцы 03.2009,04.2009, а столбец с данными 06.2009 остается пустой!
    то есть данные из детаил выводятся подряд, а не раскидываются по нужным столбцам с определенной датой!
    Как это можно исправить?!
    файл отчета в аттаче


    И еще пару вопросов, что бы темы не плодить:
    1. Как передать TStringList из Delphi в FastReport?
    2. FR по умолчанию два раза проходит по отчету или это где то указывается?
  • отредактировано 18:25
    ssvd написал: »
    вот файл отчета, к нему подключается два DBDateset соединенных как master-detail
    мастер - это строки, а детаил - это столбцы.
    допустим в мастер есть запись №1, в детаил на нее есть 4 записи с датами 03.2009,04.2009,05.2009,06.2009
    есть запись №2, в детаил на нее есть 2 записи с датами 03.2009,06.2009
    и тд.
    И когда формируется отчет то записи смещаются влево, то есть данные второй записи смещаются на столбцы 03.2009,04.2009, а столбец с данными 06.2009 остается пустой!
    то есть данные из детаил выводятся подряд, а не раскидываются по нужным столбцам с определенной датой!
    Как это можно исправить?!
    файл отчета в аттаче
    У вас фактически получается кросс таблица и так просто это не сделать.
    Для примера самая первая строка выводит такие столбцы: 03.2009,04.2009,05.2009
    а вторая : 03.2009,06.2009
    Получается кроме того, чтобы смесить столбцы нужно еще добавить один столбец(пустой) в конец первой строки.
    Но туда уже вернутся нельзя, бэнды просто печатают данные из датасета, т.е. сколько записей. столько и будет строк столбцов.

    В Вашем случае придется нормализовать данные в матрицу, т.е. перед выводом объектов заполнить эту матрицу как это делать CrossTab.

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

    ssvd написал: »
    И еще пару вопросов, что бы темы не плодить:
    1. Как передать TStringList из Delphi в FastReport?
    Report.Script.AddObject('MyStringList',MyStringList);
    ssvd написал: »
    2. FR по умолчанию два раза проходит по отчету или это где то указывается?
    Menu -> Report -> Options -> general -> Doubble pass
  • отредактировано December 2009
    написал: »
    У вас фактически получается кросс таблица и так просто это не сделать.
    Для примера самая первая строка выводит такие столбцы: 03.2009,04.2009,05.2009
    а вторая : 03.2009,06.2009
    Получается кроме того, чтобы смесить столбцы нужно еще добавить один столбец(пустой) в конец первой строки.
    Но туда уже вернутся нельзя, бэнды просто печатают данные из датасета, т.е. сколько записей. столько и будет строк столбцов.

    В Вашем случае придется нормализовать данные в матрицу, т.е. перед выводом объектов заполнить эту матрицу как это делать CrossTab.

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

    Report.Script.AddObject('MyStringList',MyStringList);

    Menu -> Report -> Options -> general -> Doubble pass

    Спасибо! Оцените вот такую стратегию:
    Передаю из Delphi - StringGrid c датами и при выводе Вертикального я перебираю StringGrid и сравниваю с датой которая должна будет выводиться! Если даты не совпадают, то вывожу пустой Бэнд, если совпадают, то вывожу с данными.
    Так можно реализовать?

    Начал делать следующее, посмотрите где я ошибаюсь!?:

    procedure Page1OnManualBuild(Sender: TfrxComponent);
    var
    DataSet,DataSet2: TfrxDataSet;
    begin
    DataSet := MasterData1.DataSet;
    DataSet2 := MasterData2.DataSet;
    DataSet.First;
    DataSet2.First;
    Engine.ShowBand(Header2);
    i:=0;

    if Engine.FinalPass then
    begin
    while not DataSet.Eof do
    begin
    Engine.ShowBand(MasterData1);
    while not DataSet2.Eof do
    begin
    if List=<frxDBTNdet."MONTHDATE"> then
    begin
    Engine.ShowBand(MasterData2);
    DataSet2.Next;
    end else
    begin
    Memo32.Text:=List;
    Engine.ShowBand(MasterData3);
    DataSet2.Next;
    end;
    end;
    DataSet.Next;
    inc(i);
    end;
    end;
    end;


    По передаче, делаю как Вы сказали:
    frxReport.Script.AddObject('ArrayDate',StringList1);

    насколько я понял, в FR надо добавить эту переменную?!
    обращаться с этой переменной как со StringList?
  • отредактировано 18:25
    Еще можно сделать так:

    Выбрать запросом все уникальные даты из детали(если нельзя запросом, можно и в цикле пройтись по всем полям датасета, но запрос будет все-таки побыстрее) и заполнить список. Count этого списка будет определять кол-во столбцов. Т.е. вместо привязки Вертикального бэнда к датасету устанавливаем его RowCount := list.count. Создать переменные в отчете, которые послужат псевдонимами для полей. При печати столбца сверять дату со списком, если дата совпала устанавливать значения переменных значениями из датасета, переключить датасет на новую запись. Если дата не совпала, то сбрасывать значения и печатать пустой столбец.
    Скрипт будет выглядеть примерно так:
    var ColumnIndex : integer;
    ds: TfrxDataSet;
      
    procedure MasterData2OnBeforePrint(Sender: TfrxComponent);
    begin
      if List[ColumnIndex] = <frxDBTNdet."MONTHDATE"> then
      begin
        Set('Var1', <frxDBTNdet."Val1">);  // установка значений переменным
        Set('Var2', <frxDBTNdet."Val2">);  
        ds.Next;// следующая запись
      end
      else
      begin
        Set('Var1', ''); // сброс значений пустая колонка 
        Set('Var2', '');
      end;                  
      inc(ColumnIndex);            
    end;
    
    procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
    begin
      ColumnIndex := 0; 
      ds.First;                                   
    end;
    
    begin
      MasterData2.RowCount := List.Count;  
      ds := Report.GetDataSet('frxDBTNdet');
    end.
    
    Где:
    MasterData1 - горизонтальный бэнд.
    MasterData2 - вертикальный бэнд.
    'Var1', 'Var2' - переменные отчета (Report- Variables) используются как псевдонимы для полей.

    В этом случае OnManualBuild не нужен.

    В приложении нужно только правильно заполнить список с датами и передать его в скрипт.

    frxReport.Script.AddObject('ArrayDate',StringList1); должен быть вызван перед PrepareReport.
    Этот код добавляет переменную в скрипт с именем ArrayDate которая будет ссылается на StringList1.
    Работать с ней можно как с обычным StringList.

  • отредактировано 18:25
    Спасибо! Как говорится: все гениальное -просто!
    Вот все сделал, вроде бы должно работать, но выпадает в ошибку! не могу понять почему!
    Access violation at address 04CEA5C1 in module 'fs5.bpl' Read of address 0000000

    Судя по ошибке - это ссылка на не созданный объект, но все вроде как создается и создано...
    вот файлик, посмотрите пожалуйста!

    даты вношу временно в процедуре frxReportOnStartReport(Sender: TfrxComponent);

    а вообще будет из delphi по frxReport.Script.AddObject('List',StringList1);
  • отредактировано 18:25
    ssvd написал: »
    Спасибо! Как говорится: все гениальное -просто!
    Вот все сделал, вроде бы должно работать, но выпадает в ошибку! не могу понять почему!
    Access violation at address 04CEA5C1 in module 'fs5.bpl' Read of address 0000000

    Судя по ошибке - это ссылка на не созданный объект, но все вроде как создается и создано...
    вот файлик, посмотрите пожалуйста!

    даты вношу временно в процедуре frxReportOnStartReport(Sender: TfrxComponent);

    а вообще будет из delphi по frxReport.Script.AddObject('List',StringList1);
    Скорее всего, добавляете объект StringList1 раньше чем создаете его в приложении.
    Должно быть что-то вроде:

    StringList1 := TStringList.Create();
    frxReport.Script.AddObject('List',StringList1);
    Заполнение
    Report.PrepareReport;

    А возможно просто не находит датасет Report.GetDataSet('frxDBTNdet') , убедитесь в правильности имени.
  • отредактировано December 2009
    написал: »
    Скорее всего, добавляете объект StringList1 раньше чем создаете его в приложении.
    Должно быть что-то вроде:

    StringList1 := TStringList.Create();
    frxReport.Script.AddObject('List',StringList1);
    Заполнение
    Report.PrepareReport;

    А возможно просто не находит датасет Report.GetDataSet('frxDBTNdet') , убедитесь в правильности имени.

    после обследования выяснилось следующее:
    ругалось на MasterData2.RowCount :=List.Count;
    List создавался на событии procedure frxReportOnStartReport(Sender: TfrxComponent);
    перенес List := TStringList.Create(); в главный begin end; ругаться перестал!
    Событие frxReportOnStartReport идет уже после главного begin end; ?

    Теперь ругается на переменные! вот к примеру: memo12: Ошибка в выражении ": Expression expected"
    все перерыл, голову сломал, на что там можно ругаться! Переменные завел правильно!
  • отредактировано 18:25
    Забыл сказать что строки в переменных должны быть в двойных кавычках, т.е. пустая строка будет выглядеть так:
    set('var1_','''' + '' + '''');

  • отредактировано 18:25
    написал: »
    Забыл сказать что строки в переменных должны быть в двойных кавычках, т.е. пустая строка будет выглядеть так:
    set('var1_','''' + '' + '''');

    я про это уже нашел на форуме, спасибо! )))
    вот в ходе дела еще вопросик возник!
    событие MasterData1OnBeforePrint(Sender: TfrxComponent); один раз выполняется или после вывода каждой строчки?
    Что то не могу найти событие , что бы выполнялось при выводе каждой строчки, что бы обнулять ColumnIndex, его же надо с каждой строчкой на начало передвигать!?
  • отредактировано 18:25
    ssvd написал: »
    я про это уже нашел на форуме, спасибо! )))
    вот в ходе дела еще вопросик возник!
    событие MasterData1OnBeforePrint(Sender: TfrxComponent); один раз выполняется или после вывода каждой строчки?
    Что то не могу найти событие , что бы выполнялось при выводе каждой строчки, что бы обнулять ColumnIndex, его же надо с каждой строчкой на начало передвигать!?

    Событие OnBeforePrint вызывается перед выводом объекта, т.е. для бэнда оно вызывается каждый раз при выводе новой строки (столбца, для вертикального).
  • отредактировано 18:25
    Все сделал!!!

    to -=Den=-
    Спасибо большое за разъяснения и помощь! Приятно был удивлен отзывчивости службы поддержи!!!
    Удачи!!! :)

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

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