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 Visual Designer page.'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
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. 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, si
We need to set this parameter before printing. Don't forget to save your changes, and return to, 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:
Now, when we execute the report, we are going to see the string we set as a parameter printed.
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 earlier.
Hint: You can use the OnMirrorValue event of the DataMirrorSection to work on ranges of values.
Now return toand 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:
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 separately.
We've learned how to work on the Visual Designer, and seen a few tricks that allow some flex
Rave有自己的可视报表设计器,以自己的文件格式保存报表。这有一些优势，你可以把报表独立于应用程序之外，可独立进行升级，甚至可以通过网络进行更新,或者使用Nevrona的Rave Report Server。当然，你也可以把报表保存为标准的DFM文件格式。
为了启动可视报表设计器,防止一个TRvProject部件在form上，这个TRvProject部件将是你的应用程序和你即将要创建的报表的联系。 如果需要，可加一个TRvSystem部件到窗体上，通过设定RvProject的Engine属性与它挂接。RvSystem部件是作为一个通用的报告系统配置部件：可通过它设置将要使用的打印机，边界，页数等等。为了开始一个新的报表项目，双击RvProject部件,或者通过敏感菜单选择"Rave Visual Designer..." 。
procedure TFormMain.btnExecuteClick(Sender: TObject);
在新的一个页面中创建一个参数HeaderKind。 它可能的值为H0 (无页头), H1(第一种页头), H2 (第二种页头)。在全局页面中增加一个新的section组件,它具有第二种页头风格。
返回到ConditionalReport报告Page1的页面，加一个DataMirrorSection部件，设定它的DataField字段为Param.HeaderKind。打开它的DataMirrors属性编辑器，增加两个Data Mirrors: 如果值是H1,将打印第一种页头；值是H2, 将打印第二种页头；因为值为H0并不匹配任何mirrors,将不打印页头。
procedure TFormMain.btnExecuteClick(Sender: TObject);
case cmbReports.ItemIndex of
1: RvProject.SetParam('Name',edName.Text); //给特定参数设定值
2: RvProject.SetParam('HeaderKind',Format('H%d',[cmbHeaderKind.ItemIndex])); //给特定参数设定值