- 1 Overview
- 2 Starting with LazReport
- 3 Functions
- 4 See also
This page started as a translation of the Portuguese language Tutorial de LazReport (which itself appears to be a translation from a French document). It was updated for LazReport (instead of FastReport) on Lazuars (instead of Delphi), using T*Connection instead of a DBase table.
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 assuming you already have your database set up as specified in SQLdb Tutorial0. If not, please do so.
Setting up your form
Place the following components on the form:
- A T*Connection, e.g. TIBConnection:
- DatabaseName := your database, e.g. C:\Program Files\Firebird\Firebird_2_5\examples\empbuild\EMPLOYEE.FDB
- UserName, Password, HostName: as appropriatie (e.g. SYSDBA,password,<none> for Firebird embedded)
- Transaction: TSQLTransaction1
- Active: true
- SQL: select * from employee
- DataSource1.DataSet := SQLQuery1
- frDbDataSet.DataSource := DataSource1
- 2 TButton
- Button1.Caption := 'Editing'
- Button2.Caption := 'Preview'
This results in:
Double-click on the TfrReport icon (or right-click, Design Report) to bring up the report designer:
Setting up variables
LazReport lets you link 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 create a variable for our database fields FIRST_NAME, LAST_NAME etc.
In the File menu, click Variables list. Now you get an overview of the defined variables:
Click on the button Variables in order to define some variables. Write the contents according ot the following image. "Demo Variables" represents a category and the other entries (xxx field) represent variables. To differentiate the two, the variables start with a space.
Finally click on OK to confirm your entries, and you'll see this:
As you can see, the category we defined is shown in the ComboBox above the variables. Each variable must be linked with a field. To do this, select the variable and then the field. Do this for all variables; the screenshot shows the link for Hire date:
Objects and bands
After closing the variables editor, we're back in our report designer. You may have noticed a small number of objects in the object bar to the left of the report surface. These are:
- the mouse icon pointer
- rectangle object
- picture object
- draw lines
- insert barcode object
Click the band icon, go to the report surface, and click on it to drop a band object.
You must click on the type of band you want to create. Select Report title and click OK.
|Report title||Shown only on the first page|
|Report summary||Shown only on the last page|
|Page header||Shown at the top of each page|
|Page footer||Shown at the bottomof each page|
|Master header||Shown at the beginning of the first detail band/level|
|Master data||First detail level data; repeated for each record in dataset|
|Master footer||Shown at the end of the first detail band/level|
|Detail header||Shown at the beginning of the second detail band/level|
|Detail data||Second detail level data|
|Detail footer||Shown at the end of the second detail band/level|
|Subdetail header||Shown at the beginning of the third detail band/level|
|Subdetail data||Third detail level data|
|Subdetail footer||Shown at the end of the third detail band/level|
|Column header||Shown at the top of every column|
|Column footer||Shown at the bottom of every column|
|Group header||Shown at the top of every group|
|Group footer||Shown at the bottom of every group|
|Cross header||Shown at the top of cross tables/pivot tables|
|Cross data||Shows cross tables/pivot table data|
|Cross footer||Shown at the bottom of cross tables/pivot tables|
In the Report title band, add a rectangle. The text editor will show up. In the first line the title of the report should be indicated. On the the second, system date and time need to be added. They are obtained by clicking Variable and then Category Other, then double-click on the desired variable (once you are familiar with the variables, you can also just type them). Now we have:
Click OK to exit the editor, then adjust the title rectangle to the desired size. Choose a color for the background with the Bucket Fill button on the toolbar.
The main event: showing data in the master data band
Let's insert a master data band. LazReport prompts you for a data source; choose frDBDataSet1, the main data source for our example. The master band will be repeated for each record in the data source. You can double-click later on the band if you want to change the data source.
In the left half of the band we insert a rectangle and double click. The familiar text editor appears.
Now we will add several fields in the one rectangle. If needed though, you can use one rectangle per field if you want to apply different formatting etc.
The first line Name [Full name field] is obtained by writing Name and then, with the Variable button, entering the variable [Field Name]. Alternatively, as indicated before, you can write the resulting text directly.
The next line Salary [Salary field] is written similarly.
The third line - Salary divided by job grade [[Salary field]/[Job grade field]] - is done likewise. This shows you can perform calculations with fields coming from the data source. Note the extra set of square brackets around the calculation. As you may guess, you can not only use the variables listed via the Variable button, but also database fields via DB Field'.
A picture is worth...
to do: we'll need to add a database field for images. Also check how this works as Laz images have an image identifier prepended in the field data by default... which is useful to keep. 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:
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:
Close the report editor and save the report definition as lazreporttutorial.lrf.
Loading the report from the form
Now let's write the code required to load and view or edit our report. To this add the following code to the project:
TForm1.Button2Click(Sender procedure: TObject); begin frReport1.LoadFromFile('lazreporttutorial.lrf'); frReport1.ShowReport; end; TForm1.ButtonClick(Sender procedure: TObject); begin frReport1.LoadFromFile('lazreporttutorial.lrf'); frReport1.DesignReport; end;
You have a preview option that gives end users a way to modify the report without changing the basic application.
Now we're going to add features to our basic example.
Add a TButton component with Caption := 'Print...', and a TPrintDialog. Behind the scenes, a project dependency on the Printer4Lazarus packages will be added by the IDE, so make sure that package is installed.
We end up with this:
Now add the printers unit to your form's uses clauses.
Put the following code in the OnClick event of the Print button:
procedure TForm1.Button3Click(Sender: TObject); var FromPage, ToPage, NumberCopies: Integer; ind: Integer; AppDirectory: String; Collap: Boolean; begin // Load report definition from application directory AppDirectory:=ExtractFilePath(ParamStr(0)); frReport1.LoadFromFile(AppDirectory+'lazreporttutorial.lrf'); // Need to keep track of which printer was originally selected to check for user changes ind:= Printer.PrinterIndex; // Prepare the report and just stop if we hit an error as continuing makes no sense if not frReport1.PrepareReport then Exit; // Set up dialog with some sensible defaults which user can change with PrintDialog1 do begin Options:=[poPageNums ]; // allows selecting pages/page numbers Copies:=1; Collate:=true; // ordened copies FromPage:=1; // start page ToPage:=frReport1.EMFPages.Count; // last page MaxPage:=frReport1.EMFPages.Count; // maximum allowed number of pages if Execute then // show dialog; if succesful, process user feedback begin if (Printer.PrinterIndex <> ind ) // verify if selected printer has changed or frReport1.CanRebuild // ... only makes sense if we can reformat the report or frReport1.ChangePrinter(ind, Printer.PrinterIndex) //... then change printer then frReport1.PrepareReport //... and reformat for new printer else exit; // we couldn't honour the printer change if PrintDialog1.PrintRange = prPageNums then // user made page range selection begin FromPage:=PrintDialog1.FromPage; // first page ToPage:=PrintDialog1.ToPage; // last page end; NumberCopies:=PrintDialog1.Copies; // number of copies // Print the report using the supplied pages & copies frReport1.PrintPreparedReport(inttostr(FromPage)+'-'+inttostr(ToPage), NumberCopies); 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 (Report: string) procedure to load the report and print.
When double clicking on frReport1, in the report designer File>Page Options menu you get this:
Select paper size:
Via File>Report Options you can set a default printer that will be used for the report (using the "Select when report loaded" checkbox).
If you want to include the total number of pages with the page number on each page, you need to select Two-pass report (which tells Lazreport to build the report twice, inserting total number of pages on the second run).
General purpose variables
Now we'll add some report variables unrelated to the database data in our example. They let you e.g. show different names according to the context.
Return to Lazarus (do not forget to save your report, if necessary) and set up the OnGetValue event of the frReport1' component by adding the following code:
procedure TForm1.frReport1GetValue(const ParName: String; var ParValue: Variant ); begin // Conditionally assign value: 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:
|Logical||>, <, BUT, AND, NOT, =, < >, > =, < =|
|Mathematical||-, *, +, MOD, /|
Further you can use the following standard functions:
|FORMATDATETIME||Formatted date and time|
|FORMATFLOAT||Formatted float value|
|NAMECASE||Initial capitals, rest lowercase|
|STRTODATE||String converted to date|
|STRTOTIME||String converted to time|
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.
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.
You can also set the color of the background and style and color of the used font by selecting Intensified brightness.
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
- 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"
- 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 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>
- 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.
- 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.
- 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 >
- 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 report then File>List and this window will appear:
You may notice the appearance of a small (...) button, active only in the case of an expression. Click below to open the editor:
You may notice the similarity. If you click the Add button it will load the editor parameters:
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.
- Tutorial de LazReport Version used as a basis for this translation.