Introduction to Rave Reports - Part II: Visual Designer
In the Part I of this document, you have seen how the Code Based engine of
Rave Reports works. Now we are going to explore the Visual Designer.
The Visual Designer
If you are used to work with Quick Reports, the default reporting engine included
in the previous versions of Delphi, you created your reports using Delphi's
own form designer, and they were save in the DFM, included as resources in your
executable. Rave works a bit diferently in this aspect: it has it's own report
designer, and saves the report using it's own file format. This has some advantages,
including the fact that your reports can be made "standalone", and
be used or updated independently of your application, or even made available
in a Intranet or in the Internet, using Nevrona's Rave
Report Server. Of course, you can still have it saved in a form's DFM.
To get started with the Rave Visual Designer, drop a TRvProject in a form.
This will be the link from your application to the reports you are developing.
If you want, you can add a TRvSystem and link your RvProject to it, through
it's Engine property. The RvSystem is the object responsible for the general
configuration of the reports: the printer that is going to be used, the margins,
the number of pages, and so on. To start a new project, double click the RvProject
you added to the form, or select "Rave Visual Designer..." from its
context menu. This is the interface that you will be working on:
The interface is simple, and you might be familiar with some parts
of it from Delphi's IDE. On the top there's the menu, the toolbar, and the component
pallete that contain the components that will be used in the reports. In the
left there's the Object Inpector, which will be used to adjust the properties
of the components of the report. In the middle there's the Page Designer or
the Event Editor, and in the left there's the very usefull Project Treeview.
For a quick overview of the components in the pallete, you can go to Nevrona's
Visual Designer page.
A Rave Project File can have one or more reports. That way you
can keep common items between them in a single location, called Global Pages.
If you expand the Report Library node of the Project Treeview, you can see that
right now you are working on Report1. Clicking on it, its properties will show
on the Inspector. Let's change it's name and call it SimpleReport. Next, go
to the Standard tab on the Component Pallete, and pick a Text component and
add it to the page. Change its text property, and adjust its size and position.
Here's how mine looked like:
As you can see, the properties that were changed from the default
values are shown in bold. In this case, I changed the Font, Text and Truncate
properties. By default it does not highlight Name, Pos and Size changes. If
you'd like to see them, right click the Inspector and uncheck "Exclude
Name, Size and Pos changes" in the context menu.
You might have also noticed that Rave does not
have an auto size property. You can use the Truncate property to have that effect:
if truncate is false, the design time size will have no effect.
You can see the result of this simple report right on the designer: Press F9
or use File/Execute Report to run it. Now let's do it in our
application. Save your project and return to Delphi. Change to ProjectFile property
of RvProject to point to the file you just saved. To run the report, add a call
to the Execute method of the RvProject object in a button click, for example.
RvProject.Execute will only work for now because we only have
one report in this project. If we had multiple reports, we'd have to call SelectReport
to choose one before calling Execute, or calling ExecuteReport directly.
Here's the output:
Tip: If you Close and Open your project before executing,
you won't need to to recompile your application or restart it to see the changes
you just made in the designer.
Interacting with the Project
If you worked with Quick Reports, you might be used to manipulating the objects
in runtime, changing their Position, Text and Visibility. After all, they were
just TObjects! While this is possible with Rave, and I'll cover it in a later
article, it's a little harder than it was with QR. But don't worry, Rave provides
a different answer to this kind of problems.
If you can use parameters in your reports. They can be defined using the parameters
property of either the Project, a Report or a Page. Parameters can be defined
in either of these places, they are just in multiple places for easier access.
You can only select the Project and a Report through the Project
Treeview. A page, however, can be selected using the Project Treeview or clicking
on it's title above the page designer.
Among other uses, you can print parameters. So, for instance, if the title
of your report can be user-defined, you could pass it from your application
into the report as a parameter.
Let's add a new report to this project to see how parameters work. To do that,
click the fourth button on the toolbar or choose File/New Report. Call it ParametrizedReport,
changing its name through the object inspector. This report is going to be very
similar to the first one, except the text is going to be user-defined.
Now we need to define the parameter that is going to be printed. To do that,
still having the report as the selected object, open the property editor the
the parameters property. There should be listed all parameters of this report,
each on a separate line. Add a parameter called Name, like this:
Parameters can be printed using a DataText component, available
in the Report tab of the component pallete. Add a DataText to the page, and
open the property editor of the DataField property. There you can choose which
field is going to be printed, when working with DataAware reports (which will
be covered on Part III of these series). You can also choose Project Variables,
Parameters and Post-Initialize Variables from there.
So choose the parameter added previously from the Parameters drop-down
combo and press the Insert Parameter button. The data text expression is now
Param.Name (we are going to change that a little later). Press
OK and try to execute the report, as before. Nothing is printed, since the parameter
has not been set.
We need to set this parameter before printing. Don't forget
to save your changes, and return to Delphi, adding a call to SelectReport before
Execute, so we can see the right report. Before executing, though, we need to
set the parameter we added. That is made using RvProject's SetParam method.
This is how my code looks like right now:
procedure TFormMain.btnExecuteClick(Sender: TObject);
Now, when we execute the report, we are going to see the string we set as a
Tip: You can use RvProject.GetReportList to get a list of
avaible projects, and add them to a ComboBox, or a RadioGroup, for example.
That makes selecting the report easier.
But this is too simple. Let's change the expression that is going to be printed.
Return to Rave Designer and open the property editor for the DataText we added.
You can add any text you want, combining text, fields, parameters and variables.
I changed it to this:
Here's the result:
Post-Initialize Variables, or simply PI Vars, are variables
whose value is only known after the report has already been printed. It may
sound strange, at first, but think about the number of pages of a report, for
example. We can only know it's value after the report is ready. Actually TotalPages
is a report variable that acts like a PI var, and can easily be printed using
DataTexts as we did with Parameters.
When you have parts of reports that are common to two or more
reports, you can put these in a global page. Let's supose we have a header with
our company name, the date and time that report is being printed, the current
page and the number of pages of that report. We want that header to be in every
report. How can we do it?
First, add a global page to the project, using File/New Global
Page, or the Toolbar shortcut. In that page, add a section component, available
in the standard tab of the component pallete.
Sections are logical groupings of components.
they can be used to group component so they can be easily moved around the report,
or as containers for Mirrors, as we are doing right now.
Inside that section we add what we want to be printed. In this case, a few
DataTexts. My header looks like this:
Hint: Instead of changing the font property
of several components to the same font, link them to a FontMaster component,
available in the standard tab, and set the font on it. That way is easier to
change the font in the future, in case it's needed.
Now add another section to the Page1 of SimpleReport. Set its Mirror property
to GlobalPage1.Section1. You will see a copy of the header you created in the
global page. Do the same thing to ParametrizedReport. Now both reports share
the same header. Here how it looks like for me:
Sometimes we need to print certain parts of a reporting depending
of some conditions. Rave has a very powerful way of dealing with this. We can
conditionally mirror sections depending on field values or parameters. Let's
create a new Report, calling it a ConditionalReport.
Let's pretend that this new report is a trick one. The user
can choose the header that is going to be printed, from two different kinds
of headers. He can also choose for the report to be printed without a header.
We are going to use a parameter to tell the report what kind of header is going
to be printed, and a DataMirrorSection to select the proper header at runtime.
First, add a parameter to this new report called HeaderKind.
Let's assume that it will have the values H0 (for no header), H1 (for the first
header), H2 (for the second kind of header). Now add a new section to the global
page (you can reach it through the Project Treeview), with the second kind of
header layout. I created a header similar to the first one, changing the font
title and adding a border around the values. It looks like this:
Now return to the Page1 of ConditionalReport, and add a DataMirrorSection,
available at the Report tab of the component pallete. Go to its DataField property
editor, and set Param.HeaderKind as the expression. Now go
to the DataMirrors property editor, and add two Data Mirrors: if the value is
H1, it should point to the first header, H2, to the second. Since H0 does not
match any mirrors, nothing will be printed. It should look like this:
Notice that I gave more meaningful names to each of the sections
Hint: You can use the OnMirrorValue event
of the DataMirrorSection to work on ranges of values.
Now return to Delphi and add the code to set the parameter according to the
user's choice. I added a ComboBox with the options and my code looks like this:
procedure TFormMain.btnExecuteClick(Sender: TObject);
case cmbReports.ItemIndex of
Now the proper header will be printed according to the user's choice.
Embedding the Project in the Executable
When you deploy your application, you must include you project file. You can
have it as a separated file, so you can update it in a easier way, only shipping
a new one, without recompiling your application, or include it in your executable.
It's easy to do that: open the property editor for the StoreRAV property of
RvProject. There you can press Load to include the file in the DFM, Save to
extract a previously saved file, and Clear to remove an embedded file. When
there's a file loaded in this property, you don't need to ship the project file
We've learned how to work on the Visual Designer, and seen a few tricks that
allow some flexible reports. You can find a project containing the sample reports
developed here on CodeCentral.
On Part III we are going to learn how to create DataAware reports, and operate