Difference between revisions of "LazReport Tutorial"

From Free Pascal wiki
Jump to navigationJump to search
m (more fixes)
Line 5: Line 5:
 
==Starting with LazReport==
 
==Starting with LazReport==
 
We're going to use a demo database which is provided by Delphi (DBDEMOS). You'll need to create a new application with a main form ''Form1''.
 
We're going to use a demo database which is provided by Delphi (DBDEMOS). You'll need to create a new application with a main form ''Form1''.
''To do: rewrite the tutorial with the database as used in the other DB tutorials, i.e. [[SQLDB Tutorial0]]''
+
''To do: rewrite the tutorial with the database as used in the other DB tutorials, i.e. [[SQLdb_Tutorial0]]''
  
 
Place the following components on the form:
 
Place the following components on the form:
Line 347: Line 347:
 
;STR(<X >) : Returns the string representation of number < X >
 
;STR(<X >) : Returns the string representation of number < X >
  
===Logical/boolean functsions===
+
===Logical/boolean functions===
 
;IF(<X>, <Y>, <Z >) : Returns < Y > if expression < X > is true. If false, returns retorna < Z >.
 
;IF(<X>, <Y>, <Z >) : Returns < Y > if expression < X > is true. If false, returns retorna < Z >.
  

Revision as of 14:58, 13 December 2013

Overview

This page is a translation of the Portugues language Tutorial de LazReport. Note: this tutorial was translated without following the steps with LazReport; adjustments of variable names etc may be necessary. Please feel free to do so.

Starting with LazReport

We're going to use a demo database which is provided by Delphi (DBDEMOS). You'll need to create a new application with a main form Form1. To do: rewrite the tutorial with the database as used in the other DB tutorials, i.e. SQLdb_Tutorial0

Place the following components on the form:

  • TTable:
  • Table1.DataBaseName := DBDEMOS
  • Table1.TableName := ANIMALS.DBF
  • Table1.Active := TRUE
  • TDataSource
  • DataSource1.DataSet := Table1
  • TfrDBDataSet
  • frDbDataSet.DataSource := DataSource1
  • TfrReport
  • TfrDesigner
  • 2 TButton
  • Button1.Caption := 'Editing'
  • Button2.Caption := 'Preview'


This results in:

imagem1.jpg

LazReport lets you associate variable names to database fields or system values, in order to spare your end users from having to decipher cryptic field names. In our example, we're going to attempt to create a variable for our fields BMP and NAME in Table1:

imagem2.jpg

Click on Variables Editor...

imagem3.jpg

Now click on the button Variables to define the left side of this windows.

imagem4.jpg


Write the contents according ot the following image. Demo Variables represents a category and FieldXXX represents the variables. To differentiate the two, the variables start with a space. Finally click on OK to get the following:

imagem5.jpg

he category is arranged in the ComboBox above variables. Each variable must be associated with a field. To do this, select the variable and then the field. The Field Name variable is associated with the Name field of Table 1.

As for the variables, click the right mouse button on the component and then frReport in New State (probably new object or something?). You then opened the editor: imagem6.jpg

You may have noticed a small number of objects in the object bar:

imagem7.jpg

The objects are equal to QRLabel, QRMemo, etc. as used in QuickReport components:

imagem8.jpg

In our blank report you must click on the type of band you want to create. Select a stage title and click OK.

Band type Use
Report title Published only on the first page
Report summary Published only on the last page
Page header Published at the top of each page
Page footer Published at the bottomof each page
Master header Published at the beginning of the first detail band/level
Master Data First detail level data
Master Footer Published at the end of the first detail band/level
Detail header Published at the beginning of the second detail band/level
Detail Data Second detail level data
Detail Footer Published at the end of the second detail band/level
Subdetail Header Published at the beginning of the third detail band/level
Subdetail Data Third detail level data
Subdetail Footer Published at the end of the third detail band/level
Overlay
Heading of column Published at the top of every column
Column base Published at the bottom of every column
Heading of group Published at the top of every group
Foot of group Published at the bottom of every group
VarColumn Used for cross tables/pivot tables

In this range, add a rectangle/box (to do: what is the terminology?) and the desired size. Choose a color for the background with the Fill Bucket(?) button, then double click the box to indicate the title.

imagem9.jpg

In the first line the title of the report should be indicated. On the the second, two details of the system used(?) need to be added. They are obtained by clicking DB Field and then in Other in the ComboBox. Now we have:

imagem10.jpg


Let's insert a master data band, then double click this band to select frDBDataSet1, the main data source for our example.

imagem11.jpg

In the left half of the band we insert a rectangle and double click:

imagem12.jpg

Here we can place several fields, but a rectangle for a single field can be retained in order to apply formatting, for example.

The first line Name [Field Name] is obtained by writing Name and then, with the Variable button, entering the variable [Field Name] (alternatively, you could have written this directly - how?)

The second line - Size [[Table1, "SIZE"] * 2.54]: we write Size and with the DB Field button choose the Size field of Table1. Then to convert this from inches to centimeters, we multiply by 2.54.

Now on the right side of the band, select an image. If you want to always show the same picture, you'd just need to double click on the picture and upload the desired image. However, let's press F11 to show the Object Inspector:

imagem13.jpg

Enter the property with the Memo [ImageField] property. This turns the picture into an object associated with the data field. Our first stage is completed. Save it with same name rapff. A click on the preview gives us:

imagem14.jpg

Now let's write the code required to load and view or edit our rap1frf report. To this add the following code to the project:

TForm1.Button2Click(Sender procedure: TObject);  
begin 
  frReport1.LoadFromFile(' rap1.frf');  
  FrReport1.ShowReport;  
end;
TForm1.ButtonClick(Sender procedure: TObject);  
begin 
  frReport1.LoadFromFile(' rap1.frf');  
  frReport1.DesignReport;  
end;

You have a preview option that gives end users the possibility to modify the report without changing the basic application.

Now we're going to add features to our basic example. You must add a TButton component with Caption := 'Print', and a TPrintDialog. We end up with this:

imagem15.jpg

Also add the printer units in the uses clause of your form and put the following code in the OnClick event of the Print button:

TForm1.bPrintClick(Sender procedure: TObject);  
var
  FromPg, ToPg, Cpy: Integer;  
  ind: Integer;  
  St: String;  
  Collap: Boolean;  
begin 
  // Load report definition
  St:=ExtractFilePath(ParamStr(0));  
  frReport1.LoadFromFile(St+' rap1.frf');  
  // Mudando a impressora padrão
  ind: = Printer.PrinterIndex;  
  // Preparar o estado; para sair se a preparação não  funcionar
  if not frReport1.PrepareReport then Exit;  
  // inicializa a limpeza do diálogo para edição de parâmetros
  with PrintDialog1 C 
  begin 
    Options:=[poPageNums ]; // allows selecting pages/page numbers
    Copies: = 1;           // apenas uma espécie
    Collate: = True;     // cópias ordenadas
    FromPage: = 1;     // start page
    ToPage: = frReport1.EMFPages.Count;  //  last page
    MaxPage: = frReport1.EMFPages.Count; // maximum number of pages
    if Execute then    //    limpeza do diálogo   
    begin 
      if (Printer.PrinterIndex < > ind ) // a impressora mudou?   
        or frReport1.CanRebuild // possui uma regeneração de estado? 
      // mudança de impressora   
        or frReport1.ChangePrinter(ind, Printer.PrinterIndex) then                
        frReport1.PrepareReport  
      else Exit; / / a mudança de impressora ocorreu de forma errônea 
    if PrintDialog1.PrintRange = prPageNums then // fez-se uma seleção de páginas
    begin 
         FromPg : = PrintDialog1.FromPage; // first page
         ToPg : = PrintDialog1.ToPage;      // last page
    end; 
    Cpy :=PrintDialog1.Copies;   // number of copies
    Collap :=PrintDialog1.Collate;  // order copies
    // recorte de edição da página FromPg com ToPg  , " Cpy " 
    // exemplares ordenados  (Collap))  
    frReport1.PrintPreparedReport(FromPg, ToPg, Cpy, Collap);  
    end; 
  end; 
end;

It's a bit long, but if needed, you can create a descendant of TfrReport with an easier printing method or class , create a PrintReport (State: string) procedure to load the report and print.

In the Edit File> Page Options menu you get this:

imagem24.jpg

Select paper size:

imagem16.jpg

Choose desired margins:

imagem17.jpg

You can specify the number of columns and the space between them. In the editor's main menu, select File> Report options to display the following dialog box:

imagem18.jpg

Here you specify the printer required for loading states and the preparation is done in two ways.

  • If you want to include the total number of pages in your page number, you should choose the Two-pass report options.

Here we'll add some variables unrelated to the data to our example. They make it possible, for example, to show the different names according to the context.

To do this, open the report editor and select the File menu and the Variable List. Test with a variable, as explained above. The only difference is that you will not select a value field, but leave None (the default value). Save the objects and add the Test variable as seen previously. Return to Lazarus (do not forget to save your report) and use the OnGetValue event of the FrRepor1 component by adding the following code:

procedure TForm1.frReport1GetValue(const ParName: String;  
var ParValue: Varying; VAr fld: TField);  
begin 
 // deal with variable number of dependencies
 if UpperCase(ParName)=' TEST' then 
   ParValue:=' Answer: Variable " test1 " ';  
end;

Alternatively, you can also pass the value directly to the variable using the following code:

procedure TForm1.Button1Click(Sender:TObject);
begin
  frReport1.Values.FindVariable('test').Field := QuotedStr('test1');
  frReport1.ShowReport;
end;

The below(?) is not used for data iself, but to enable formatting the data with DisplayFormat.

Now let's see how to create a calculated variable. As before, we will create a new category (optional) and a variable. Test Calculation(?).

Select a new variable and select a value from the ComboBox "Other" and "Expression". This selection activates data entry for Expression. Type the following: [Table1 "SIZE".] + [Table1 "WEIGHT."]. That way you will get the sum of the fields of Size and Weight data (which is a bit ridiculous but it shows the principle). You can also use the variable name. You can also use the following operators:

Operator type Operators
Logical >, <, BUT, AND, NOT, =, < >, > =, < =
Mathematical -, *, +, MOD, /

Further you can use the following standard functions:

Function Descriptions Examples
SUM Sum
AVG Average
MIN Mínimum
MAX Maximum
FORMATDATETIME Formatted date and time
FORMATFLOAT Formatted float value
LOWERCASE Lowercase text
NAMECASE Initial capitals, rest lowercase
STRTODATE String converted to date
STRTOTIME String converted to time
UPPERCASE Uppercase text

If this is not enough you can create your own functions, but that we will see later.

Now we define a format for the variables of an area. A format is valid for all variables of a display area. To show the format editor, click the right button on an area and then in Variable Format.

imagem19.jpg

The first ComboBox indicates the type of data (text, numeric, date, time, logical/boolean). The second allows you to select a preset format. The Text type does not allow any Number type formatting. The Number type requires a decimal number with a comma (to do: verify this. Is this country specific?). Except for Text and Logic types, you can use the formatting features of Lazarus.

You can also include the concept of highlighting, which is very useful for emphasizing data. You can specify a condition that determines when highlighting is applied. For that use the keyword Value to indicate the value of the variable. Here is the highlighting for all values greater than 1000. By default highlighter is a simple bold on white background. You can set these parameters to an area by clicking the Highlight button.

imagem20.jpg

You can also set the color of the background and style and color of the used font by selecting Intensified brightness.

Functions

You need to add the following line to the file FR.lng (is this still the correct name for Lazreprot?):

, FCT = CATEGORY | FCT (<X> <Y>, <z>) | Help function on the

where:

  • FCT is the function name.
  • CATEGORY is the category name.
  • FCT (<X> <Y>, <z>), is the layout of the required parameters, with a maximum of 3 parameters.
  • Help Is a small help text which should allow the user to understand the purpose of the function.
  • | is a separator.

Each parameter is separated by commas and can be an expression, a constant, a variable, a field or data. Alphanumeric type constants should be limited by a character. The variables are delimited by and.

Data fields are limited to the variables and have the following format:

Dataset_Name. "Field_Name"

Statistical functions

SUM(<X >)
Returns the sum of values represented by <X>, which is generally a data field.
AVG(<X >)
Returns the average of <X> values.
COUNT
Count the number of occurrences.
MIN(<X >)
Returns the lowest value of all values represented by <X>
MAX(<X >)
Returns the highest value of all values represented by <X>

Date functions

FORMATDATETIME(<X>, <Y >)
Returns <Y> TDateTime in format <X>. <X> uses the default syntax for Lazarus formats.
FORMATFLOAT(<X>, <Y >)
Returns the numeric value <Y> in format <X>. <<X> uses the default syntax for Lazarus formats.
STRTODATE(<X >)
Returns the TDateTime(? not date?) representation of string < X >. < X > must be formatted correctly.
STRTOTIME(<X >)
Returns the TDateTime time part representation of string < X >. < X > must be formatted correctly.

String functions:

LOWERCASE(<X >)
Returns lowercase <X>
UPPERCASE(<X >)
Returns uppercase <X>
NAMECASE(<X >)
Returns <X> with initial capitals
COPY(<X>, <Y>, <Z >)
Similar to Pascal Copy: returns string <X> from position < Y > for < Z > characters.

Numeric functions

FRAC(<X >)
Returns the decimal part of number < X >
INT(<X >)
Returns the integer part of number < X >
ROUND(<X >)
Returns the number < X > rounded to an integer (up? down? nearest integer? banker's rounding?)
STR(<X >)
Returns the string representation of number < X >

Logical/boolean functions

IF(<X>, <Y>, <Z >)
Returns < Y > if expression < X > is true. If false, returns retorna < Z >.

To add your own functions is really quite simple. Some source code to add the functions POS and SQRT below:

Unit FR_OGFct;
interface 
implementation 
uses FR_Pars, FR_Class; // Standard declarations needed for Lazreport!! Note: FR_pars etc? Are these names ok?
type 
 // Our own functions are declared here.
TfrOGFunctionLibrary = class(TfrFunctionLibrary)
 public  
  constructor Create; override;  
  procedure DoFunction(FNo:integer procedure;  p1, p2,
             p3:Variant; var valley:string); override;  
             p3:Variant; var valley:string);
 end;  
//************************** 
// * TfrOGFunctionLibrary 
constructor TfrOGFunctionLibrary.Create;
begin  
 inherited Create;  
 // Add our functions to the list of available functions:
 with List do 
 begin
  Add('POS');
  Add('SQRT');
 end;
end;

Procedure TfrOGFunctionLibrary.DoFunction(FNo:Integer procedure;  p1,
p2, p3:Variant; Var valley:String); //valley?
Var 
  Par1, Par2:  Varying;
  Result:  Variantying; //variantying? variant?
begin
Try
 Case FNo of  //this is the index of the functions as added in the constructor
  0 : 
	begin   // POS  function
    Par1:=VarToStr(Parser.Calc(p1)); 
    Par2:=VarToStr(Parser.Calc(P2)); 
    Result:=Pos(Par1,Par2);
  end;
  1 :  // SQRT function
	Result:=SQRT(Parser.Calc(P1));
 end;
Except   
 // String with error details
 Result:='Error in function '+List.Strings[FNo];
end;
Val:=VarToStr(Result); // Resulting string
end;

rocedure DoInit;
begin
 frRegisterFunctionLibrary(TfrOGFunctionLibrary);
end;

In the FR.lng file, you'll need to add the following lines:

SQRT = Matemática e Trigonometria | SQRT(<X>) |Retorna a raiz quadrada de <X>
POS = Strings | POS(<X>,<Y>) Retorna a posição da string <X> em <Y>

Publish a state?file?report? then File>List and this window will appear:

imagem21.jpg

You may notice the appearance of a small (...) button, active only in the case of an expression. Click below to open the editor:

imagem22.jpg

You may notice the similarity. If you click the Add button it will load the editor parameters:

imagem23.jpg

Depending on the number of parameters, you have more or less edit areas. The (...) button makes it possible to open the expression generator to set the parameter.

See also