Проблема с Header и Footer

отредактировано 07:09 Раздел: FastReport 3.0
Собственно имеется отчет, у которого сводные данные по группам выводятся не после детальных данных, а перед ними:
Всего группа 1:
первый результат в группе 1
второй результат в группе 1
третий результат в группе 1
Всего группа 2:
первый результат в группе 2
второй результат в группе 2

Примерно так.
- Создал MasterData
- Создал GroupHeader, назначил выражение для объединения. Допустим идентификатор группы.
- Далее сделал GroupFooter, в него добавил текстовое поле с содержимым:
[SUM(<AQOQuery1."QTY">,MasterData1)]

Предпросмотр отчета показыает, что все отлично, итог считается правильно по группам.
Осталось понять как можно его записать в GroupHeader.

Как вариант попробовал так:
procedure IllnessFooterMemoOnAfterData(Sender: TfrxComponent);
begin
      IlnessHeaderMemo.Text := IllnessFooterMemo.Text;
end;

В итоге данные из футера перемещаются в хедер следующей группы, а не текущей!

Кто-нибудь умеет аггрегированные данные вставлять в хедер?

Комментарии

  • отредактировано 07:09
    Еще "5 копеек в копилку". Если данные присваивать только на первом проходе (not Engine.FinalPass) то во всех хедерах будет только последнее присвоенное значение последнему хедеру. Другими словами, не зависимо от того что мы присваивали всем хедерам, их результат будет равен последнему присвоению первого прохода (если во втором проходе ничего не изменять).
  • отредактировано 07:09
    Я, конечно, с одной стороны слепой, посколько подобный пример, оказывается, расписан в руковдстве оператора на стр. 116.

    Попробовал использовать второй способ и ... ничего не получилось.
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
      if Engine.FinalPass then
        IllnessHeaderMemo.Text := Get(<Razdel2_AQ."IG_ID">);
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
      Set(<Razdel2_AQ."IG_ID">, '2222');
    end;
    
    Ошибка во время выполнения оператора в теле if:
    Были oбнapyжeны cлeдyющиe oшибки:
    He мoгy пpeoбpaзoвaть вapиaнт типa (String) в тип (Currency)

    Попробую идентификатор преолбразовать в строку:
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
      if Engine.FinalPass then
        IllnessHeaderMemo.Text := Get(IntToStr(<Razdel2_AQ."IG_ID">));
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
      Set(IntToStr(<Razdel2_AQ."IG_ID">), '2222');
    end;
    
    Ошибка:
    Были oбнapyжeны cлeдyющиe oшибки:
    He мoгy пpeoбpaзoвaть вapиaнт типa (Null) в тип (OleStr)
    Heизвecтнaя пepeмeннaя или пoлe БД: 1

    По сути
    Get(IntToStr(<Razdel2_AQ."IG_ID">)) дает Null
    а
    IntToStr(<Razdel2_AQ."IG_ID">) - '1',
    то есть преобразованное число.

    Пусть это неправильный идентификатор, попробуй добавить префикс:
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
      if Engine.FinalPass then
        IllnessHeaderMemo.Text := Get('var' + IntToStr(<Razdel2_AQ."IG_ID">));
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
      Set('var' + IntToStr(<Razdel2_AQ."IG_ID">), '2222');
    end;
    
    Ошибка:
    Были oбнapyжeны cлeдyющиe oшибки:
    He мoгy пpeoбpaзoвaть вapиaнт типa (Null) в тип (OleStr)
    Heизвecтнaя пepeмeннaя или пoлe БД: var1

    При этом если смотреть сразу значение переменной после присваивания, то все на месте!:
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
      if Engine.FinalPass then
        IllnessHeaderMemo.Text := Get('var' + IntToStr(<Razdel2_AQ."IG_ID">));
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
      Set('var' + IntToStr(<Razdel2_AQ."IG_ID">), '2222');
      IllnessHeaderMemo.Text := Get('var' + IntToStr(<Razdel2_AQ."IG_ID">))
    end;
    
    Последний оператор нужен чтобы проверить в режиме отладки. Get возвращает '2222', так почему в другом вызове он ее не возвращает?

    Господа, ткните меня носом в ошибку! ;)
  • отредактировано 07:09
    Похоже я нашел ошибку, или по крайней проблема в следующем:
    я попробовал в последней строке
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
     if Engine.FinalPass then
       IllnessHeaderMemo.Text := Get('var' + IntToStr(<Razdel2_AQ."IG_ID">));
    end;
    
    вычислить не для текущего значения IG_ID значение переменной, а для следующего (просто запомнил второе значение). В итоге там находится '2222', как мы и присваивали жестко. И для третьего и т.д., а для первого значения там Null. Это баг? Версия 3.17.
  • отредактировано 07:09
    В общем то ли все сломалось, окончательно, либо он между двумя этими событиями не видит переменных. По крайней мере без отладки я получил большое количество ошибок:
    написал:
    Были oбнapyжeны cлeдyющиe oшибки:
    Heизвecтнaя пepeмeннaя или пoлe БД: var1
    Heизвecтнaя пepeмeннaя или пoлe БД: var101
    Heизвecтнaя пepeмeннaя или пoлe БД: var111
    Heизвecтнaя пepeмeннaя или пoлe БД: var121
    Heизвecтнaя пepeмeннaя или пoлe БД: var129
    Heизвecтнaя пepeмeннaя или пoлe БД: var144
    Heизвecтнaя пepeмeннaя или пoлe БД: var155
    Heизвecтнaя пepeмeннaя или пoлe БД: var163
    Heизвecтнaя пepeмeннaя или пoлe БД: var173
    Heизвecтнaя пepeмeннaя или пoлe БД: var184
    Heизвecтнaя пepeмeннaя или пoлe БД: var197
    Heизвecтнaя пepeмeннaя или пoлe БД: var22
    Heизвecтнaя пepeмeннaя или пoлe БД: var220
    Heизвecтнaя пepeмeннaя или пoлe БД: var255
    Heизвecтнaя пepeмeннaя или пoлe БД: var40
    Heизвecтнaя пepeмeннaя или пoлe БД: var46
    Heизвecтнaя пepeмeннaя или пoлe БД: var5001100
    Heизвecтнaя пepeмeннaя или пoлe БД: var5002100
    Heизвecтнaя пepeмeннaя или пoлe БД: var5003100
    Heизвecтнaя пepeмeннaя или пoлe БД: var5004100
    Heизвecтнaя пepeмeннaя или пoлe БД: var5005100
    Heизвecтнaя пepeмeннaя или пoлe БД: var5006100
    Heизвecтнaя пepeмeннaя или пoлe БД: var54
    Heизвecтнaя пepeмeннaя или пoлe БД: var65
    Heизвecтнaя пepeмeннaя или пoлe БД: var76
    Heизвecтнaя пepeмeннaя или пoлe БД: var87
    Heизвecтнaя пepeмeннaя или пoлe БД: var91
  • отредактировано 07:09
    Кстати можно ли получить как нибудь список текущих переменных (например через глобальную переменную типа Engine) ?
    И какие кроме Engine переменные еще определены? И где об этом найти информацию? А то гадать как-то не очень продуктивно получается...

    Спасибо.
  • отредактировано 07:09
    Попробуйте сделать вызов set и get для всех групп (у вас set только для GroupFooter1, а get GroupHeader4).
  • отредактировано 07:09
    Вопрос понял. Вы возможно заметили, что у меня имеется GroupHeader4 и GroupFooter1. На самом деле у меня четыре страницы в отчете. Первые три работают правильно (там Set и Get вообще не используются, все стандартно). А 4 я добавил, чтобы была нормальная нумерация элементов (на X странице ReportTitleX и т.д.), а вот номер у футера не изменил. Но идея интересная, пробую сделать отдельный простой отчет.

    Начал новый отчет, и получил следующее:
    SQL:
    написал:
    select 1 as GRP_ID, 'Группа1' as GRP_NAME, 1 as EL_ID, 'Элемент 1.1' as EL_NAME, 1 as VAL
    union
    select 1, 'Группа 1', 2, 'Элемент 1.2', 3
    union
    select 1, 'Группа 1', 3, 'Элемент 1.3',10
    union
    select 2, 'Группа 2', 4, 'Элемент 2.1', 2
    union
    select 2, 'Группа 2', 5, 'Элемент 2.2', 7

    Создал все по руководству, назначил события:
    procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
    begin
      if Engine.FinalPass then
        IllnessHeaderMemo.Text := Get('var' + IntToStr(<ADOQuery1."GRP_ID">));
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
      Set('var' + IntToStr(<ADOQuery1."GRP_ID">), <SUM(<ADOQuery1."VAL">,MasterData1)>);
    end;
    

    И ... все заработало. Сейчас попробую выяснить почему такая ошибка появляется в реальном отчете.
  • отредактировано 07:09
    Прошу прощения у всех, что побеспокоил, но виноват кажется я.
    procedure GroupHeader4OnBeforePrint(Sender: TfrxComponent);
    begin
     if Engine.FinalPass then
       IllnessHeaderMemo.Text := Get(<Razdel2_AQ."IG_ID">);
    end;
    
    procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
    begin
     Set(<Razdel2_AQ."IG_ID">, '2222');
    end;
    
    Когда я здесь описывал выражения, я поставил не то поле. IG_ID у меня обозначает конкретный элемент, а не группу. Поэтому когда я заменил на идентификатор группы, то все заработало.

    Но остался вопрос, почему не работало, когда был идентификатор элемента? Ведь если переменная создана и там было значение '2222', то в Null оно не должно "просто так выставляться". По крайней мере в GroupHeader4OnBeforePrint выдавал мне Null (функция Get). Идентификаторы то одни и теже, а порядок правильный (GroupFooter1OnBeforePrint а затем GroupHeader4OnBeforePrint). В общем, тут вопрос остается открытый.

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

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