Ask Reuben
Starting With Genero Report Writer (part 1 of 2)
What is Genero Report Writer?
How do I write my first Genero Report Writer?
What can you do with Genero Report Writer?
When people start using our newer products I often see them jumping in the deep end, trying to run before they can walk, biting off more they can chew etc. and their first experiences are not as positive as they can be. Over time I am going to do a series of articles entitled “Starting …” where I will explain what I think are the key concepts and points you should understand with our products and try and make your initial experience a positive one. Today I will look at Genero Report Writer (or GRW). One of the keys to having a positive experience with Genero Report Writer is understanding the architecture. A number of times when explaining concepts to developers I will point them back at this diagram that can be found in the documentation here.
Architecture
Genero Report Writer is available as a standalone product. In the architecture diagram, you see the purple Genero BDL. That purple section can be replaced by a number of other languages and you can see more of that at https://generoreportwriter.com. For the purposes of this article I will concentrate on use of Genero Report Writer with Genero BDL.
Unlike a number of other reporting tools, Genero Report Writer does not interact with the database directly. Note in the diagram how data from the database (yellow) is extracted by the Genero BDL language (purple) before being used as input by the Genero Reporting Engine (red). Your 4gl logic is responsible for extracting the data required to produce the report. This allows you to use your business rules with this data rather than being limited to what SQL allows.
Genero Report Writer (GRW) consists of three products, Genero Report Designer (GRD), Genero Report Engine (GRE) and Genero Report Viewer (GRV), the three red squares in the diagram. It is important to note that these three products can exist on different machines. So if you are designing a report using the Genero Report Designer on your Windows PC and you select a font from the drop down, is that same font available on the server used by the Genero Report Engine, and is that font available on the device that the report is viewed on? The scripts fontinfo, fontinfopdf, printerinfo can be run on each individual machine to see what is available. Your system administrators will have to be familiar with ensuring that systems are configured to have the required font files, and that printers are appropriately configured.
The Genero Report Engine effectively takes two inputs, a datastream and a report design. From this it produces the formatted report.
A designer designing a report using the Genero Report Designer requires as input a data schema (the .rdd file) that describes the format of the datastream
The architecture typically means that there are two people working closely producing a report. A 4gl focussed developer who is tasked with producing a datastream and a data schema. A report designer who receives the data schema and probably some sample datastreams, so that they can design and produce reports. They need to work close together, if the report designer says they need some additional data in the datastream then they need to get the 4gl focussed developer to produce a new data schema and sample datastreams.
A concept that Genero Report Writer has is the streaming concept. Note that the datastream is called a “stream”, it is not a data file or database. A stream of data is pumped into the Genero Report Engine and the output is produced when it can. That is if all the information is page 1 is available, it will be output. So when printing large documents, rather than having the entire document in memory, it is typically the case that physical printing of page 1 can be started whilst page 2 is being created. There are exceptions to this, most notably when printing Page X of Y, we can’t physically print Page 1 until we know what Y is.
This datastream can be captured in a file and reused. So in the development process, rather than continually hitting the yellow database to run the same report repeatedly, this datastream can be captured in a file, and the file streamed to the Genero Report Engine multiple times as you fine tune a report design.
Documentation
At this time, the documentation for Genero Report Writer is found inside the Genero Studio documentation. It has been considered to seperate it out into its own documentation but for the moment it is bundled with the Genero Studio documentation. The person working on the datastream and the surrounding 4gl program will work closely with this section, whilst the person designing the graphical report will use this section. There are also a number of training videos available.
Installation
The Genero Report Engine is available as a separate download. It is typically installed on the same server as the Genero BDL package, it can be installed on a seperate server but to start with you would keep it on the same server. Just as in $FGLDIR, there is envcomp to set the minimum environment, in $GREDIR there is envgre that contains the minimum environment required. A 4gl Genero application needs to use the libraries that in GREDIR/lib/libgre.42x so you will typically need to remember to add libgre.42x as an external dependency.
The Genero Report Engine makes use of a number of Java libraries and so you need to ensure that a version of Java is installed. The GRE installation should check this and the supported systems documentation details the Java requirements. If you peek inside GREDIR/bin/greportwriter you will see that it executes a Java program.
The Genero Report Designer is bundled inside Genero Studio. Even if you don’t use Genero Studio for your day to day 4gl work, you should still download and use it to edit report designer files. There is a seperate Genero Report Designer package available but we suggest you use Genero Studio.
First Report / Compatibility Mode
The first report you can attempt is to take one of your existing 4gl Reports and output in what we call compatibility mode. This can be used to illustrate the various output modes. In terms of architecture this is where if we don’t pass a specified report design to the Genero Report Engine, it will calculate a design from the page, line and column numbers inherent in the 4gl report produced by the 4gl REPORT statement.
In effect this enables you to take an existing ASCII report and output it to PDF or any of the other report formats. To do this, find the START REPORT line of a simple report in your system and make the following changes …
DEFINE grw om.SaxDocumentHandler IF NOT fgl_report_loadCurrentSettings(NULL) THEN RETURN NULL END IF CALL fgl_report_selectDevice("PDF") CALL fgl_report_selectPreview(TRUE) LET grw = fgl_report_commitCurrentSettings() START REPORT report_name TO XML HANDLER grw -- START REPORT report_name TO ... # comment out existing START REPORT line
…, add libgre.42x as an external dependency (or link to it), you should now get your original report output as a PDF. You can then experiment with the fgl_report_selectDevice and the fgl_report_selectPreview calls initially to try different formats, and then the wide range of fgl_report functions that can change other settings for the report.
If the report does not come out neatly aligned, or it overflows to the right, add a call to fgl_report_configureCompatibilityOutput() between fgl_report_loadCurrentReport() and fgl_report_commitCurrentSettings() and pass an appropriate value for RIGHT MARGIN as the first argument and “Monospaced” for the second argument. This is because either your report does not have a RIGHT MARGIN explicitly set and so the reporting engine has assumed 132, or because the default font is not present and the fallback font is not proportional. A value of “Monospaced” should ensure a monospaced font is used.
If you are curious about how the compatibility report is fitted and placed on the page that was explained in an earlier Ask-Reuben.
External Reporting Concepts
When it comes to designing and working with reports, you will need to be familiar with …
Monospaced Font v Proportional Fonts
The available Units of Measure. Sizing can be done in metric (cm, mm), imperial (inches). Historically printing was done using a concept of points. You can also use these units of measure which include points, and pica.
Paper sizes. This includes the orientation, and how to make a page portrait or landscape via fgl_report_configurePageSize().
Colour, the various way to define a colour.
Internal Reporting Concepts
For working with our reports there are some concepts that are important
Absolute v Relative Positioning. You will find that the best report design makes heavy use of Relative Positioning and that you should avoid falling into the trap of dragging objects from the Toolbox or Dataview into the designer and positioning things absolutely.
Simple v Propagating containers. A propagating container will duplicate itself when it is full. For example, a page is a propagating container, when it is full, a new page is created with headers/footers. A WordBox is not a propagating object, a new word box is not created if you fill it.
?: ternary operator. This is used in expressions, and maybe unfamiliar to a 4gl developer. Essentially if a property is expressed a?b:c, then if a is true then the value of the property is b, else the value of the property is c. This is equivalent to the IIF operator in 4gl i.e IIF(a,b,c)
Expressions and the two sub-groups of expressions, RTL and PXML . I differentiate between RTL and PXML by thinking back to the architecture and breaking the creation of a report into two passes. In the first pass, property values are resolved from the values in the data-stream. So if you have value<0?Color.RED:Color.BLACK then this is resolved on the first pass where it checks the values in the data-stream and sets the color to red if the value is negative, I think of this as RTL. The second pass is then when the page is being put together or laid out and you might have an expression that impacts on the way elements are laid out on a page. For example, width(“M”)*20 and this is saying the value of the expression is the width needed to write 20 M’s using the current font properties, I think of this as PXML. To begin with you do not need to worry too much about the difference between the two, but as you build more complex reports you may need to start asking yourself, is this going to change the way objects are laid out on a page, particular when RTL is embedded inside PXML.
om.SaxDocumentHandler. You will note that the argument passed to XML HANDLER is of type om.SaxDocumentHandler. Essentially this class allows you to process the XML as it is received in the datastream.
Tutorials and Samples – Report
In Genero Studio, in the Tutorials and Samples tab there is project “Reports”. To see what Genero Report Writer is capable of, you can run the “OrderReport” program. The ComboBox has a number of reports, and these all correspond to a .4rp in the Designs folder.
You should run this program and experiment with the different reports and look at the individual .4rp to see how they are put together.
Your First 4gl
One area where my opinion varies from the GRW team is the layout of the 4gl program. I tend to create the 4gl to have the following basic structure
FIRST PAGE HEADER -- Fill report with information unique to the report e.g. author, creation date/time PRINT report.* BEFORE GROUP OF ... -- Fill header will information unique to the group e..g PRINT header.* ON EVERY ROW -- Fill detail with information unique to the row e.g. PRINT detail.* AFTER GROUP OF -- Fill header_total using GROUP SUM etc to calculate totals PRINT header_total.*
That is more personal choice but IMHO it helps keep the 4gl clearer. I find that the structure used by OrderReport.4gl with everything in the ON EVERY ROW is not as clear.
There are some key concepts. The role of the 4gl program is to gather data, not to format it. So the 4gl program should gather as much data and include it in the data stream. I give this example, you should include:
- the price excluding tax
- the price including tax
- the tax amount
- a flag if tax is include
The report designer can then choose which of these to use. If you don’t include all then you maybe forcing the report designer to do some calculations and you then run the risk of rounding etc. giving different values.
Another concept is to minimise the amount of PRINT that are included in an IF, FOR, WHILE loop etc. These will come through into the report design. So you should not have
IF include_tax_flag THEN PRINT price_inclusive_tax ELSE PRINT price_exclusive_tax END IF
Keep the PRINT simple with
PRINT price_inclusive_tax, price_exclusive_tax, tax, include_tax_flag
Finally it is not the job of the 4gl datastream to think about page breaks. Hence the REPORT 4gl should not have any PAGE HEADER, PAGE TRAILER blocks, concentrate on gathering the data and let the 4gl lay out the page.
Once you have the REPORT statement as you want it then you need to create the .rdd and pass it to the report designer so they can design the report.
Designing a .4rp report file is another topic in itself and I cover the basics of that in the next article.
Final Point – Saving and Reusing the Datastream
Final point I want to make here is how to save and reuse a process level data file. This enables you to save the datastream and reuse this saved file to produce a report.
To create the file, when setting up the XML handler, you can use fgl_report_createProcessLevelDataFile() to save the datastream to a file instead of passing it through the Genero Report Engine. You can also use fgl_report_setProcessLevelDataFile() to save the datastream at the same time as producing a report.
Once you have the datastream then it is very simple to rerun a report using fgl_report_runReportFromProcessLevelDataFile() . You can build a very simple 4gl program to run a report over and over again
MAIN DEFINE grw om.SaxDocumentHandler IF NOT fgl_report_loadCurrentSettings("filename.4rp") THEN EXIT PROGRAM 1 END IF CALL fgl_report_selectDevice("PDF") CALL fgl_report_selectPreview(TRUE) LET grw = fgl_report_commitCurrentSettings() CALL fgl_report_runReportFromProcessLevelData(grw, "datastream.xml") END MAIN
Your support contact will have a very simple program like that and they will ask you for .4rp, .rdd, and the process level data file. That is a concept you should get yourself familiar with so that you too can make changes to a report very quickly and see the result.
Summary
There is a lot in Genero Report Writer. In next article I will illustrate using the report designer and some of the key concepts in designing your report.