Wellcome to RReport, the package that will allow you to include printing, reporting and prevewing capablities into yourJava [TM] or Web applications (JDK 1.1 or newer) in a few minutes. RReport is located in the package com.java4less.rreport
The main features or RReport are:
Before you start reading this section you must note that there are 2 ways for creating reports:
You can, of course, also combine both approaches. For example, you can create a report template (*.rep file) and modify it at runtime.
There are 3 classes that represent a report
A Rreport is made of Rareas. A RArea is a group of objects (RObject) that will be printed together (in the same page). Typical examples of areas in a report are:
The source code to create an area looks like this:
// create report
Rreport Rep=new RReport(MainWindow);
// if you use java 1.2 or later you can use
// Rep=new RReportJ2(null);
RArea HDR_PurchaseOrder= new RArea();
HDR_PurchaseOrder.width=16.429;
HDR_PurchaseOrder.height=4.074;
Rep.addArea(HDR_PurchaseOrder);
As already stated, an RArea contains of a set of objects (RObject). These are the elements that are actually printed. The following Robjects are currently available:
The following example creates the page footer for the Purchase order report:
RArea PFOOTER_PurchaseOrder= new RArea();
RField TextPageNumber=new RField();
TextPageNumber.name="TextPageNUmber";
TextPageNumber.setConstant(false);
TextPageNumber.setdefaultValue("[Page]");
TextPageNumber.x=0.238;
TextPageNumber.y=0.185;
TextPageNumber.width=3;
TextPageNumber.height=0.423;
TextPageNumber.Align=RField.ALIGN_LEFT;
TextPageNumber.Expand=false;
TextPageNumber.Compress=false;
TextPageNumber.FontColor=java.awt.Color.black;
TextPageNumber.FontType=new java.awt.Font("Arial",java.awt.Font.PLAIN,8);
PFOOTER_PurchaseOrder.add(TextPageNumber);
rep.setPageFooter(PFOOTER_PurchaseOrder);
The code:
Actually this would not be necessary. When you create a new RReport it already contains a default pager footer like this one.
Note: if you are using RReport Visual Builder you will not do this, you will read the definition of your report from a file.
If you want to modify a RField in a report created with the Visual Builder you can do it like this:
RField f=(RField) report.getAreaByName(name).getItemByName(elementName);
Areas can be nested by linking them to a superareas (see RArea.setLinkedArea() ). After a repetition of an area is printed, all subareas are printed automatically.
For example:
detailArea.setLinkedArea(headerArea);
will result in detailArea being printed after each repetition of headerArea. See RJDBCSource to learn how to retrieve the information from a database and define relationships between tables.
Lets suppose your report has 2 areas (header and detail). You have 2 options:
report.setHeaderArea(hdr);
report.addArea(detail);
report.prepare(); // this prints report header
report.printArea(detail); // we must now print the detail area
report.endReport();
report.seHeaderArea(hdr);
report.addArea(detail);
detail.setLinkedArea(hdr);
// link detail to header
report.prepare(); // this prints header and detail
report.endReport();
After you have defined your report (either programatically or with the Visual Builder) , you will need to print it. First you must decide if you want to print it directy or you want to preview it.
If you want to preview the report you need to put the RReport object on a component. The RReport object is a java.awt.Panel so you can put it on any java container. Then you must call the report‘s method setPreview(MainWindow).
You can create your own preview window however we include two preview windows. One of then is a pure AWT component (RReportWindow) and the second is a Swing component (RReportJWindow). The code to use the window is:
Win= new RReportWindow(rep,MainWindow);
// if you use SWING:
// Win= new RReportJWindow(rep,MainWindow);
report.prepare();
// Print here ....
report.endReport();
Win.show();
In order to print a report you must follow these steps:
Note: report header anf footer and page header and footers are printed automatically. If you need to execute your own code before these areas a printed you must use a RAreaListener.
Tip: if you make all your areas dependent of the report header using the setLinkedArea(), then all areas will be printed automatically when you call prepare(). (i.e. the header will be printed and all its subareas).Note: the prepare() method will print one repetition of the report header. If you assign a RSource (array, table in database ...) to the report header, several repetitions of the header and all subareas will be printed. For each new report header repetition a page break and a initialisation of the page number is automatically performed. In this way you can print more than 1 report at once.
RReport comes with two implementations of a preview window (RReportWindow and RReportJWindow ). However if you don‘t like them you can create your own preview window. RReport is an extension from Panel so you can add it to any of your applets, windows etc..
The following methods in RReport will help you building your own user interface:
Areas are programatically printed by:
However you can also use a Rsource object. In this case the report will automatically assing the values to the fields and print the area as many times as needed. There are 3 implemented Rsource classes, but you can implement your own class.
The following example uses the class RArraySource to print the lines of a Purchase Order:
private static void Example2() {
// example: array as data source
Win= new RReportWindow(rep,MainWindow);
DETAIL_PurchaseOrder.setDataSource(new RArraySource(columnsNames,columnsData));
rep.prepare();
//print here
rep.printArea(DETAIL_PurchaseOrder);
rep.endReport();
Win.show();
}
The array columnsNames contains the names of the fields and the array columnsData contanins the values. See Examples or exampleOrder.java.
Note: you can use a RAreaListener in order to execute your own java code before each repetition of the area is printed.
Note: objects defined as constant (see RObject.setConstant()) will not be modified by the data source (RSource).
The class RJDBCSource is a subclass of RSouce. It will therefore allow you to print the contents of a table in a database. Furthermore RJDBCSource supports nested areas. This means you can print an area that contains subareas.
Let's suppose you must print 2 Invoices. Invoice number 1 and invoice number 2. You have a database that contains two tables: INVOICES and INVOICESLINES.
You have defined the following areas for this:
in order to programatically print the two invoices you must:
You can easily simplify this process by using RJDBCSource in the following way.
// create source table
RJBCSource headerTable=new RJBCSource(statement,"SELECT * FROM INVOICES");
headerArea.setDataSource(headerTable);// create source table
RJBCSource linesTable =new RJBCSource(statement,"SELECT * FROM INVOICESLINES");
linesArea.setDataSource(linesTable);// link areas
linesArea.setLinkArea(headerArea);// link fields
linesTable.setToFields("ID");
linesTable.setFromFields("ID");// link tables
linesTable.setLink(headerTable);
This means the following:
You can also use parameters in your SQL statement. For example:
myJDBCSource=new RJDBCSource(statement, "SELECT * FROM INVOICES where IDate>'[%dateParam]'");
in this case you must provide a value for the parameter before you run the report:
myJDBCSource.setParameter("dateParam","01/01/2001");
Groups
A very commoun question is. How do I create groups in RReport? you must use nested areas for that.
For example, you would need up to 3 areas:
If you want to print a JTable you don‘t have to define the report’s layout field by field, the RJTable class can do it for you.
This class performs the following tasks:
The following example show how to print a Jtable in 5 minutes:
private static void Example5() {
// example: printing a JTable
Win= new RReportWindow(rep);
Win.show();
javax.swing.JTable dataTable = new javax.swing.JTable(columnsData, columnsNames);
RJTable RT=new RJTable(dataTable,0,0,10,2,1.5);
RT.createAreas();
rep.addArea(RT.getHeaderArea());
rep.addArea(RT.getDetailArea());
rep.prepare();
//print here
rep.printArea(RT.getHeaderArea());
rep.printArea(RT.getDetailArea());
rep.endReport();
Win.refreshPageNumber();
}
You first create the RJTable object and provide some information about the size. Then call the createAreas() method and last you add the new areas to you report.
This method is provided for backwards compatibility only, we advise you to use DHTML instead.
Rreport is also capable of exporting your report as HTML. This process works in the following way:
<table BORDER="0" CELLSPACING="0" CELLPADDING"0">
<tr HEIGHT=31>
<td WIDTH=5></td>
<td WIDTH=164 <%%lblPurchaseOrder%%> </td>
</tr>
</table>
<table BORDER="0" CELLSPACING="0" CELLPADDING"0">
<tr HEIGHT=31>
<td WIDTH=5></td>
<td WIDTH=164 ALIGN="LEFT"><font SIZE="2" FACE="Arial" COLOR="#000000"><STRONG>Purchase
Order</STRONG></font></td>
</tr>
</table>
where <%%lblPurchaseOrder%%> has been replaced with the actual value.
This means you can change the way the HTML is created. If you dont like how your HTML report looks like, you can override the area’s getHTML() methods an create you own layout. But remember to include "<%%fieldname%%>" where the elements must be inserted!
You could also override the Robject’s toHTML() method to change the way a Robject is converted to HTML.
RReport can also export your report to DHTML. This is usefull if you are using rreport in a web environment. We advise you to use DHTML instead of HTML because it produces better quality output.
In order to export to DHTML you must call the following methods:
rep.setHTMLActive(true); // active HTML / DHTML output
rep.setDHTMLActive(true); // select DHTML mode
rep.disablePrinting(true); // do not send output to printer/ / print report now
rep.prepare();
....
rep.endReport();// save DHTML output to file
String htmlString=rep.getHTML();
try {java.io.OutputStreamWriter out2= new java.io.OutputStreamWriter(new java.io.FileOutputStream(fileName),System.getProperty("file.encoding"));
out2.write(htmlString,0,htmlString.length());
out2.close();} catch (Exception e) { e.printStackTrace(); }
The class DHTMLLayer is in charge of converting the reports to DHTML code.
Whenever you export to DHTML you must take into account that the browser requires all to be stored in files. If you create a chart or a barcode, the resulting image must be stored in a image file. The following properties are used for the configuration of this:
report.exportImagesFormat="jpg"; // store the chart or barcode as jpg file
report.exportDirectory="c:\web\images"; // store the file in this subdirectory
report.imagesHTMLPrefix="images\"; // the resulting DHTML will look like this: <IMG SRC="images/XXXXXX.jpg" >
If you want to create GIF or PNG file you must include the following packages in your classpath:
If you are using a RPicture object for printing images, the "ImageHTMLAddress" property will be used when exporting to DHTML. In RReport Visual Builder the property is called "HTML image".
For example:
picture.ImageHTMLAddress="/images/file.jpg"
will generatee <IMG SRC="/images/file.jpg" > as part of the DHTML code. In the case of RPicture you must place the file in the correct directory, RReport will not create the file.
RReport can also export your report to PDF. This is usefull if you are using rreport in a web environment. In order to export to DHTML you must call the following methods:
rep.setPDFFile("output.pdf") // set pdf output file
rep.disablePrinting(true); // do not send output to printer/ / print report now
rep.prepare();
....
rep.endReport();
RReport uses a free Java library called iText that creates PDF files. Click here to download the pdf library. You must install the PDF library by including the iText.jar file in your class path or in the same directory as rreport.
The class PDFLayer is in charge of converting your report to PDF using iText.
If you are developing a web application you can also use RReport to create your reports. The reports can be created as DHTML pages or PDF files. In both cases the result can be displayed in the user's browser.
RReport provides a generic servlet call RReportServlet. The Servlet load a java class that implements the IWebReport interface. This interface is used by the servlet to create and run the report.
The servlet has the following parameters:
The IWebReport interface
As already stated the servlet always loads a java class that implements the IWebReport interface. This interface only has 2 methods:
The servlet performs the following steps:
RReport provides a ready to use implementation of IWebReport called "WebReportJDBC" which is used to execute reports whose data is read from a database.
The WebReportJDBC class
This class is the defaut implementation of IWebReport. It works the following way:
This class is used to load and execute reports that can read data from database. The SQL statements in the template file can contain parameters.
For example, suppose you have a report that prints employee's information. Your template file could use the following SQL statement in order to read the employee's data:
Select * from Employees where EmployeeId=[%Id]
Then the servlet should have a parameter called "PAR_ID" which provides the value for the %Id% parameter in the SQL.
You would for example, execute the servlet like this:
http://localhost:8080/rreport/servlet/RReportServlet?REPORTFILE=file://employee.rep&PAR_ID=14&FORMAT=PDF
in order to print the information of employee 14.
In order to install RReportServlet on Tomcat you must follow the following steps:
<Context path="/rreport"
docBase="webapps/rreport"
crossContext="false"
debug="0"
reloadable="true" >
</Context>
<Context path="/rreport" docBase="rreport" debug="0" reloadable="true">
Now you can test the installation
http://localhost:8080/rreport/servlet/RReportServlet?DEBUG=ON&REPORTFILE=file://order.rep&PDFDIR=../webapps&FORMAT=PDF&PDFPREFIX=/rreport/
http://localhost:8080/rreport/servlet/RReportServlet?DEBUG=ON&REPORTFILE=file://order.rep&IMAGESDIR=../webapps&IMAGESPREFIX=/rreport/
The following examples are delivered in app.java :
These are examples that programatically defined reports that will help you understand how RReport works, but it is not the best way to create reports. Read the RReport Visual Builder documentation in order to see examples of report created with RReport Visual Designer.
The following examples are included in this document:
The following source code creates a new type of Area. This area has a horizontal separator in the HTML version.
Public class myRArea extends Rarea
{
public String getHTML() {
String html=super.getHTML();
Html=html+"<hr>"; // html tag for displaying a horizontal
line
Return HTML;
}
}
You can also change the way a Robject is converted to HTML. The following code changes the HTML version of Rcombo:
Public class myCombo extends RCombo
{
public String toHTML(Object Value) {
String s;
s="";
if (Align==ALIGN_RIGHT) s=s+" ALIGN=\"RIGHT\"";
if (Align==ALIGN_CENTER) s=s+" ALIGN=\"CENTER\"";
if (Align==ALIGN_LEFT) s=s+" ALIGN=\"LEFT\"";
s=s+">";
s=s+"<font SIZE=\""+super.fontSizetoHTML(FontType)+"\" COLOR=\""+super.fontColortoHTML(FontColor)+"\">"+super.fontValuetoHTML(FontType,((String) Value))+"</font></td>";
return s;
}
}
The following source code creates a new Robject class for printing triangles:
import java.awt.*;
public class RTriangle extends RObject {
// (x1,y1),(x2,y2) and (x3,y3) make the 3 corners
public double x1=0.5;
public double y1=0;
public double x2=0;
public double y2=1;
public double x3=1;
public double y3=1;
public java.awt.Color color=java.awt.Color.black;
public RTriangle(){
constant=true; }
public void print(Graphics g,double px, double py,Object Value) {
int[] X=new int[3];
int[] Y=new int[3];
// convert from CM to pixels
X[0]=(int) (px+(x1*this.resolution));
Y[0]=(int) (py+(y1*this.resolution));
X[1]=(int) (px+(x2*this.resolution));
Y[1]=(int) (py+(y2*this.resolution));
X[2]=(int) (px+(x3*this.resolution));
Y[2]=(int) (py+(y3*this.resolution));
g.setColor(color);
g.drawPolygon(X,Y,3);
}
}
In order to create you own RObject you must extend the RObject class and implement the function:
public void print(Graphics g,double px, double py,Object Value)
you must then draw your object in the graphics context "g" at the position (px, py). The parameter "Value" can be any runtime object you need. For example, in the case of RField, "Value" is the text that should be printed and in the case of RPicture "Value" is the Image to be printed. In the case of RTriangle we don't use that parameter.
See RObject for more information about field you may need to use in your object.
Optionally you can implement the importFile() function if you want your object to be able to read itself from a report definition file:
public void importLine(String key,String val) {
super.importLine(key,val);
if (key.compareTo("COLOR")==0) {
this.color=convertColor(val); }
if (key.compareTo("X1")==0) this.x1=new Double(val).doubleValue();
if (key.compareTo("Y1")==0) this.y1=new Double(val).doubleValue();
if (key.compareTo("X2")==0) this.x2=new Double(val).doubleValue();
if (key.compareTo("Y2")==0) this.y2=new Double(val).doubleValue();
if (key.compareTo("X3")==0) this.x3=new Double(val).doubleValue();
if (key.compareTo("Y3")==0) this.y3=new Double(val).doubleValue();
}
This function receives a "key" that contains the name of the field read from the file and the value "val". See also Creating your own objects in RReport Visual Builder.
You can use the properties expand and compress to specify how the Rfield class will behave if the text is too long or too short:
You can very easily draw a frame around the page,an area, or all areas of the same type.
The following example draws a frame around the report’s page:
rep.setPageFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
The following example draws a frame around the report’s header:
PHDR_PurchaseOrder.setFrameType(RArea.FRAME_AREA);
PHDR_PurchaseOrder.setFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
The following example draws a frame around the report’s header
DETAIL_PurchaseOrder.setFrameType(RArea.FRAME_PAGE);
DETAIL_PurchaseOrder.setFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
Note that in this example only one frame for all the lines of the "purchase order" will be created. If we use RArea.FRAME_AREA instead, a frame for each line is created.
If you want to print a table you may also want to print a grid to separate rows and columns inside this table.
DETAIL_PurchaseOrder.setGrid({8,10,12});
DETAIL_PurchaseOrder.setHorizontalGrid(true);
DETAIL_PurchaseOrder.setGridStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
This code will:
If you use the RJTable class to construct your report, you dont have to worry about this. Just call:
MyRJTable.SetHRDFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
MyRJTable.SetLINFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
MyRJTable.SetLINGridFrameStyle(new RLineStyle(0.2f,java.awt.Color.black,RLineStyle.LINE_NORMAL));
To create frames and grid for the table.
Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries