Как узнать что будет напечатано в поле Memo?

отредактировано 17:59 Раздел: FastReport 3.0
Всем Здравствуйте!

Подскажите пожалуйста в каком порядке срабатывают OnGetValue и OnBeforePrint у frxReport'а? По трассировке получается, что сначала OnBeforePrint, а потом OnGetValue???? Неужели так и должно быть? Тогда как же узнать перед печатью какой текст (уже готовый, без переменных и агрегатных функций) будет выведен в поле данного Memo?

Комментарии

  • gpigpi
    отредактировано 17:59
    написал:
    По трассировке получается, что сначала OnBeforePrint, а потом OnGetValue
    именно так
    используй событие MemoOnAfterData
  • отредактировано 17:59
    Спасибо!

    Я нашёл ссылку на это событие в документации, но не совсем понятно, я, что, должен сам вписывать ссылку на обработчик этого события во все Memo документа, или его можно инициировать как-то иначе?

    И второе: в документации сказано, что:

    "Одно замечание – если в объекте содержится несколько выражений,
    например [expr1] [expr2] – в переменную Value попадет значение последнего
    выражения." -

    и какже мне увидеть ВЕСЬ готовый текст, который будет помещён в поле Memo?

  • gpigpi
    отредактировано 17:59
    написал:
    и какже мне увидеть ВЕСЬ готовый текст, который будет помещён в поле Memo?
    Для Memo1 в Memo1OnAfterData прописать
    MemoText:=Memo1.Text
  • отредактировано 17:59
    Прошу прощения, а нельзя ли примерчик, как заполучить это самое Memo1OnAfterData?
  • gpigpi
    отредактировано 17:59
    unit Unit1;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, frxClass;

    type
    TForm1 = class(TForm)
    frxReport1: TfrxReport;
    procedure frxReport1GetValue(const VarName: String;
    var Value: Variant);
    procedure FormCreate(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.frxReport1GetValue(const VarName: String;
    var Value: Variant);
    begin
    if VarName='var' then Value:='Text';
    ShowMessage('frxReportGetValue '+TfrxMemoView(frxReport1.FindObject('Memo1')).Text);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    frxReport1.ShowReport();
    end;

    end.
    ==================dfm====================
    object Form1: TForm1
    Left = 191
    Top = 114
    Width = 296
    Height = 265
    Caption = 'Form1'
    Color = clBtnFace
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    OldCreateOrder = False
    OnCreate = FormCreate
    PixelsPerInch = 96
    TextHeight = 13
    object frxReport1: TfrxReport
    Version = '3.20'
    DotMatrixReport = False
    IniFile = '\Software\Fast Reports'
    PreviewOptions.Buttons = [pbPrint, pbLoad, pbSave, pbExport, pbZoom, pbFind, pbOutline, pbPageSetup, pbTools, pbEdit, pbNavigator, pbExportQuick]
    PreviewOptions.Zoom = 1.000000000000000000
    PrintOptions.Printer = 'По умолчанию'
    ReportOptions.CreateDate = 38774.892350740740000000
    ReportOptions.LastChange = 38774.892350740740000000
    ScriptLanguage = 'PascalScript'
    ScriptText.Strings = (
    'procedure Memo1OnBeforePrint(Sender: TfrxComponent);'
    'begin'
    ' ShowMessage(''Memo1OnBeforePrint ''+Memo1.Text);'
    'end;'
    ''
    'procedure Memo1OnAfterData(Sender: TfrxComponent);'
    'begin'
    ' ShowMessage(''Memo1OnAfterData ''+Memo1.Text);'
    ' Memo1.Text:=''Corrected text'';'
    'end;'
    ''
    'begin'
    ''
    'end.')
    OnGetValue = frxReport1GetValue
    Left = 98
    Top = 58
    Datasets = <>
    Variables = <>
    Style = <>
    object Page1: TfrxReportPage
    PaperWidth = 209.973333333333300000
    PaperHeight = 296.862500000000000000
    PaperSize = 9
    LeftMargin = 10.000000000000000000
    RightMargin = 10.000000000000000000
    TopMargin = 10.000000000000000000
    BottomMargin = 10.000000000000000000
    object Memo1: TfrxMemoView
    Left = 22.000000000000000000
    Top = 24.000000000000000000
    Width = 246.000000000000000000
    Height = 16.000000000000000000
    OnAfterData = 'Memo1OnAfterData'
    OnBeforePrint = 'Memo1OnBeforePrint'
    Memo.UTF8 = (
    '[var]')
    end
    end
    end
    end
  • отредактировано 17:59
    Всё это, конечно, здорово, но мне нужен доступ к этим данным не из скрипта, а из моего кода(хотя-бы потому, что отчёты приносят "со стороны", и я не могу требовать от пользователей, чтобы они вставляли в них ещё какие-то скрипты). Я попробовал вызвать из скрипта внешнюю функцию, естественно, он её не видит...
    Так есть ещё какой-нибудь способ увидеть из внешнего кода строку, готовую к печати в Memo?
  • gpigpi
    отредактировано 17:59
    В событии Memo1OnAfterData можно через пользовательскую функцию передать значение в программу
  • отредактировано 17:59
    Как? Ведь из скрипта не видно пространства имён Form1!
  • gpigpi
    отредактировано 17:59
    unit Unit1;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, frxClass, StdCtrls;

    type
    TForm1 = class(TForm)
    Label1: TLabel;
    frxReport1: TfrxReport;
    procedure frxReport1GetValue(const VarName: String;
    var Value: Variant);
    procedure FormCreate(Sender: TObject);
    function frxReport1UserFunction(const MethodName: String;
    var Params: Variant): Variant;
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.frxReport1GetValue(const VarName: String;
    var Value: Variant);
    begin
    if VarName='var' then Value:='Text';
    ShowMessage('frxReportGetValue '+TfrxMemoView(frxReport1.FindObject('Memo1')).Text);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    frxReport1.AddFunction('function GetText(Text:string):string');
    frxReport1.ShowReport;
    end;

    function TForm1.frxReport1UserFunction(const MethodName: String;
    var Params: Variant): Variant;
    begin
    if MethodName='GETTEXT' then
    begin
    Label1.Caption:='Text in memo - '+VarToStr(Params[0]);
    Result:=Params[0];
    end;
    end;

    end.
    ====dfm====
    object Form1: TForm1
    Left = 191
    Top = 114
    Width = 296
    Height = 265
    Caption = 'Form1'
    Color = clBtnFace
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    OldCreateOrder = False
    OnCreate = FormCreate
    PixelsPerInch = 96
    TextHeight = 13
    object Label1: TLabel
    Left = 100
    Top = 38
    Width = 32
    Height = 13
    Caption = 'Label1'
    end
    object frxReport1: TfrxReport
    Version = '3.20'
    DotMatrixReport = False
    IniFile = '\Software\Fast Reports'
    PreviewOptions.Buttons = [pbPrint, pbLoad, pbSave, pbExport, pbZoom, pbFind, pbOutline, pbPageSetup, pbTools, pbEdit, pbNavigator, pbExportQuick]
    PreviewOptions.Zoom = 1.000000000000000000
    PrintOptions.Printer = 'По умолчанию'
    ReportOptions.CreateDate = 38774.892350740700000000
    ReportOptions.LastChange = 38774.892350740700000000
    ScriptLanguage = 'PascalScript'
    ScriptText.Strings = (
    'procedure Memo1OnBeforePrint(Sender: TfrxComponent);'
    'begin'
    ' ShowMessage(''Memo1OnBeforePrint ''+Memo1.Text);'
    'end;'
    ''
    'procedure Memo1OnAfterData(Sender: TfrxComponent);'
    'begin'
    ' ShowMessage(''Memo1OnAfterData ''+Memo1.Text);'
    ' {Memo1.Text:=''Corrected text'';}'
    'end;'
    ''
    'begin'
    ''
    'end.')
    OnGetValue = frxReport1GetValue
    OnUserFunction = frxReport1UserFunction
    Left = 50
    Top = 32
    Datasets = <>
    Variables = <>
    Style = <>
    object Page1: TfrxReportPage
    PaperWidth = 210.000000000000000000
    PaperHeight = 297.000000000000000000
    PaperSize = 9
    LeftMargin = 10.000000000000000000
    RightMargin = 10.000000000000000000
    TopMargin = 10.000000000000000000
    BottomMargin = 10.000000000000000000
    object Memo1: TfrxMemoView
    Left = 22.000000000000000000
    Top = 24.000000000000000000
    Width = 246.000000000000000000
    Height = 16.000000000000000000
    OnAfterData = 'Memo1OnAfterData'
    OnBeforePrint = 'Memo1OnBeforePrint'
    Memo.UTF8 = (
    '[GetText(<var>)]')
    end
    end
    end
    end
  • отредактировано 17:59
    Последний пример, окончательно сбил меня с толку!
    Проще говоря, совсем непонятно, что делать!
    Ситуация такая: пользователи программы создают новый отчёт:

    // первая колонка DataBand'а вторая колонка ..... и т.д.
    [var1] бла-бла-бла [var2] бла-бла-бла [var3] | [var4] бла-бла-бла [var5] .........

    регистрируют его у меня в системе, и я, зная, что надо подставлять вместо [var1], [var2], ..... и т.д., строю отчёт. Но перед тем как готовая, содержащая все подстановки переменных строка будет выведена в отчёт, я должен произвести из кода программы довольно сложный анализ и обработку этой строки.
    Так как-же в свете последнего примера это можно сделать?
    На мой взгляд, именно OnBeforePrint у frxReport'а и должен давать мне такую возможность!
  • LexLex
    отредактировано 17:59
    1. Опиши глобальную внешнюю(пользовательскую) функцию (см. документацию) которая в качестве параметра получает готовый текст из мемки и если нужно имя мемки, а возвращает текст который должен быть (вообщем парсер) , она будет доступна для всех отчетов.
    2. перед запуском отчета в скрипт из программы добавь обработчик(просто дописать текст перед первым Begin
    End.)
    procedure AllMemoOnAfterData(Sender: TfrxComponent)
    begin
    TfrxMemoView(Sender).Text := MyParse(TfrxMemoView(Sender).Text, Sender.Name); 
    //  MyParse - товая пользовательская функция  
    // Sender.Name елси нужно имя мемки
    end;
    
    3. Всем мемка в отчете поставить твой обработчик
    var
      i,j:integer;
    begin
      for i:=0 to frxReport1.PagesCount-1 do
        if frxReport1.Pages[i] is TfrxReportPage then
          for j:=0  to frxReport1.Pages[i].Objects.Count - 1 do
            if frxReport1.Pages[i].Objects[j] is TfrxMemoView then
              TfrxMemoView(frxReport1.Pages[i].Objects[j]).OnAfterData := 'AllMemoOnAfterData'           
    end;
    




  • отредактировано 17:59
    Вроде, всё понятно и, если не будет сильно тормозить на больших отчётах, то, то, что нужно. Но не живёт!

    По доке: создал в программе программе процедуру
    procedure TForm1.MyParse ( s: string; n: string );
    var
      str: string;
    begin
      str := s + ' ' + n;
    end;
    
    , зарегистрировал её в FR
    frxReport1.AddFunction('procedure MyParse(s: string; n: string)');
    
    в скрипте отчёта поместил обработчик OnAfterData для мемок
    procedure AllMemoOnAfterData(Sender: TfrxComponent);
    begin
      MyParse(TfrxMemoView(Sender).Text , Sender.Name);
    end;
    

    Толкаю - только молча строится отчёт.
    Через отладчик вижу, что AddFunction нормально регистрирует MyParse в FR(регистрирует саму процедуру, парсит и регистрирует список её переменных), для мемок нормально запускается AllMemoOnAfterData, но управление в
    function TForm1.frxReport1UserFunction(const MethodName: String;
    var Params: Variant): Variant;
    begin
    if MethodName = 'MYPARSE' then
      MyParse(Params[0],Params[1]);
    end;
    
    и, тем более, ко мне в MyParse не попадает!

    Где ещё грабли???
  • LexLex
    отредактировано 17:59
    попробуй почитать здесь про пользовательские функции
  • LexLex
    отредактировано March 2006
    попробывал сделать следующее

    1. пустая форма ложу frxReport и TButton.
    2.
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      frxReport1.AddFunction('procedure MyParse(s: string; n: string)');
      frxReport1.ShowReport;
    end;
    
    3.
    function TForm1.frxReport1UserFunction(const MethodName: String;
      var Params: Variant): Variant;
    begin
      if MethodName = 'MYPARSE' then
        MyParse(Params[0],Params[1]);
    end;
    
    4.
    procedure TForm1.MyParse(a, b: string);
    begin
       ShowMessage(a + ' ' + b);
    end;
    
    5. в отчете одна мемка в с обработчиком
    procedure Memo1OnAfterData(Sender: TfrxComponent);
    begin
      MyParse(TfrxMemoView(Sender).Text , Sender.Name);
    end;
    

    все работает.
    Проверь весь код еще раз.

    вот файл с отчетом
    ////////////////////////////////////////////////////
    unit1.dfm
    ////////////////////////////////////////////////////
    object Form1: TForm1
      Left = 192
      Top = 107
      Width = 870
      Height = 640
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Button1: TButton
        Left = 56
        Top = 24
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 0
        OnClick = Button1Click
      end
      object frxReport1: TfrxReport
        Version = '3.20'
        DotMatrixReport = False
        IniFile = '\Software\Fast Reports'
        PreviewOptions.Buttons = [pbPrint, pbLoad, pbSave, pbExport, pbZoom, pbFind, pbOutline, pbPageSetup, pbTools, pbEdit, pbNavigator, pbExportQuick]
        PreviewOptions.Zoom = 1.000000000000000000
        PrintOptions.Printer = #1055#1086' '#1091#1084#1086#1083#1095#1072#1085#1080#1102
        ReportOptions.CreateDate = 38778.508374224540000000
        ReportOptions.LastChange = 38778.508374224540000000
        ScriptLanguage = 'PascalScript'
        ScriptText.Strings = (
          'procedure Memo1OnAfterData(Sender: TfrxComponent);'
          'begin'
          '  MyParse(TfrxMemoView(Sender).Text , Sender.Name);'
          'end;'
          ''
          'begin'
          ''
          'end.')
        OnUserFunction = frxReport1UserFunction
        Left = 8
        Top = 16
        Datasets = <>
        Variables = <>
        Style = <>
        object Page1: TfrxReportPage
          PaperWidth = 209.973333333333400000
          PaperHeight = 296.926000000000000000
          PaperSize = 9
          LeftMargin = 10.000000000000000000
          RightMargin = 10.000000000000000000
          TopMargin = 10.000000000000000000
          BottomMargin = 10.000000000000000000
          object Memo1: TfrxMemoView
            Width = 94.488249999999990000
            Height = 18.897650000000000000
            OnAfterData = 'Memo1OnAfterData'
            Memo.UTF8 = (
              'sfsdf')
          end
        end
      end
    end
    

    ////////////////////////////////////////////////////
    unit1.pas
    ////////////////////////////////////////////////////
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, frxClass, frxDesgn;
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        frxReport1: TfrxReport;
        function frxReport1UserFunction(const MethodName: String;
          var Params: Variant): Variant;
        procedure Button1Click(Sender: TObject);
      private
        procedure MyParse(a, b: string);
      public
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    function TForm1.frxReport1UserFunction(const MethodName: String;
      var Params: Variant): Variant;
    begin
      if MethodName = 'MYPARSE' then
        MyParse(Params[0], Params[1]);
    end;
    
    procedure TForm1.MyParse(a, b: string);
    begin
      ShowMessage(a + ' ' + b);
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      frxReport1.AddFunction('procedure MyParse(s: string; n: string)');
      frxReport1.ShowReport;
    end;
    
    end.
    
  • отредактировано 17:59
    Пример тоже не идёт! Т.е. OnAfterData запускается - а дальше: тишина!
    Может быть это связано с версией Delphi? У меня D5, а примеры, я так понимаю, в более поздней(т.к. в uses есть юнит Variants, которого в D5 нет и я его убираю. При этом всё строится без проблем.) Про пользовательские функции сейчас почитаю, но думаю, это ничего не даст.
  • LexLex
    отредактировано 17:59
    да у меня D7 на пятой проверить нет возможности

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

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