RReport for .NET

 

Introduction

Wellcome to RReport, the package that will allow you to include printing, reporting (DHTML and PDF) and prevewing capablities into your .NET applications in a few minutes.

The main features or RReport are:

 

Creating a report

Before you start reading this section you must note that there are 2 ways for creating reports:

  1. you can programatically create all the objects that make a report and link them together.
  2. or you can use RReport Visual Builder in order to visually create a report. This will be exported to a definition file *.rep that you can import in your application.

You can, of course, also combine both approaches. For example, you can create a report template (*.rep file) and modify it at runtime.

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:

[c#]

// create report
Report Rep=new Report();

RArea HDR_PurchaseOrder= new RArea();
HDR_PurchaseOrder.width=16.429;
HDR_PurchaseOrder.height=4.074;
Rep.addArea(HDR_PurchaseOrder);

[vb.net]

' create report
Dim Rep as Report
Rep=new Report()

Dim HDR_PurchaseOrder as RArea

HDR_PurchaseOrder= new RArea()
HDR_PurchaseOrder.width=16.42
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:


[c#]

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=Color.Black;
TextPageNumber.FontType=new Font(new FontFamily("Arial"),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.

If you are using RReport Visual Builder you will not do this, you will read the definition of your report from a file:

 

[c#]

Report report=new Report();

if (!report.importReport("examples\\DatabaseSource\\DBorder.rep")) {
Console.WriteLine("Error, exiting");
Application.Exit();
}

[vbnet]

' load report from file
Dim report as Report

report=new Report()

Console.WriteLine("loading report")
if (not report.importReport("examples\PDF_DHTML\order.rep")) then
Console.WriteLine("Error, could not load file")
end
end if

 

If you want to modify a RField in a report created with the Visual Builder you can do it like this:

[c#]

RField f=(RField) report.getAreaByName(name).getItemByName(elementName);

[vbnet]

Dim f as RField
f=report.getAreaByName(name).getItemByName(elementName)

 

Nested (linked) Areas

Areas can be nested by linking them to a superarea (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 RDatabaseSource to learn how to retrieve the information from a database and define relationships between tables.

Let's suppose your report has 2 areas (header and detail). You have 2 options:

 

 

Group of Areas

You can create a group of areas using RReport Visual Builder. A group of areas is made of:

The groups of areas will allow you to automatically print a header and/or a footer based on the values of one or more fields.

The groups of areas must be used together with a RSource (normally a RDatabaseSource) and you should set a value for the "RArea.setGroupByFields()" property of the detail area, there is no other special treatment, you can print the group's detail area as you would print any other area.

RReport will automatically print the group header and footer areas whenever the values of the "group by" fields change. Note that the header and footer area share the same RSource as the detail area.

For example , if you are printing the following data in you group detail:

Article Id =1 , Name=Printer , Category=Hardware
Article Id =2 , Name=Scanner , Category=Hardware
Article Id =3 , Name=Antivirus , Category=Software
Article Id =4 , Name=Editor , Category=Software
Article Id =5 , Name=Linux , Category=Software

and you set Group by "Category". The result will be:

  1. Group header is printed
  2. article 1 is printed
  3. article 2 is printed
  4. Group footer is printed
  5. Group header is printed
  6. article 3 is printed
  7. article 4 is printed
  8. article 5 is printed
  9. Group footer is printed

Note that RReport will NOT SORT the values. You must provide the data for the detail area in the correct order. In the previous example you would use a sql statement like: "select * from Articles order by Category" to make sure all articles in the same category come together.

You can find an example of use of groups in the examples/groups folder.

Printing a report

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.

In order to print a report you must follow these steps:

  1. Call prepare(). This will print your report header.
  2. Print the areas. You can either print the areas by assigning the values to the elements yourself (programatically) or you can provide a data source (RSource).
  3. Call endReport(). This will print your report footer.

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.

 

The preview Window

If you want to preview the report you can:

[c#]
// use windows's default preview dialog
report.setPreview(true);
report.useSystemPreviewWindow=true;

report.prepare();

// Print here ....

report.endReport();

[vbnet]
' use windows's default preview dialog
report.setPreview(true)
report.useSystemPreviewWindow=true

report.prepare()

' Print here ....

report.endReport()

 

[c#]
Win= new RReportWindow(rep);

report.prepare();

// Print here ....

report.endReport();
Win.showNow();

[vbnet]
' create preview window
Dim Win as RReportWindow
Win= new RReportWindow(report)

report.prepare()
report.endReport()
Win.ShowNow()

If you want to create your own preview window we advise you to use our preview winvow RReportWindow.cs as starting point.

 

Data sources (Rsource)

Areas are programatically printed by:

  1. Assigning a value to the elements in the area. The following command assigns the value "Article1" to the element "TextDescription".
    DETAIL_PurchaseOrder.getItemByName("TextDescription").setruntimeValue("Article1");
  2. and Calling the report’s printArea() method: rep.printArea(DETAIL_PurchaseOrder);
  3. or if they are linked to a superarea, after the superarea is printed.

However you can also use a Rsource object. In this case the report will automatically assign the values to the fields and print the area as many times as needed. There are 2 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:

[c#]

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 .

Note: you can use a RAreaListener in order to execute your own 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).

 

Reading from database (RDatabaseSource)

The class RDatabaseSource is a subclass of RSouce. It will therefore allow you to print the contents of a table in a database. Furthermore RDatabaseSource 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:

  1. Retrieve the header's data for invoice 1 (you should query the database like "SELECT * FROM INVOICES WHERE KEY=1")
  2. print header 1
  3. Retrieve the lines for invoice 1 (you should query the database like "SELECT * FROM INVOICESLINES WHERE KEY=1")
  4. print all lines for invoice 1
  5. Retrieve the header's data for invoice 1 (you should query the database like "SELECT * FROM INVOICES WHERE KEY=2")
  6. print header 2
  7. Retrieve the lines for invoice 2 (you should query the database like "SELECT * FROM INVOICESLINES WHERE KEY=2")
  8. print all lines for invoice 2

You can easily simplify this process by using RDatabaseSource in the following way.

[c#]

// create source table
OleDbConnection con1=new OleDbConnection();
con1.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\RReportNET\\RReport2.mdb";
con1.Open();

OleDbCommand sta1=con1.CreateCommand();
sta1.CommandText="SELECT * FROM INVOICES";

RDatabaseSource headerTable=new RDatabaseSource(con1,sta1);
headerArea.setDataSource(headerTable);

// create source table

OleDbConnection con2=new OleDbConnection();
con2.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\RReportNET\\RReport2.mdb";
con2.Open();

OleDbCommand sta2=con.CreateCommand();
sta2.CommandText="SELECT * FROM INVOICES";

RDatabaseSource linesTable =new RDatabaseSource(con2,sta2);
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:

  1. Assign the table INVOICES as source for headerArea.
  2. Assign the table INVOICESLINES as source for linesArea.
  3. area linesArea (subarea) is linked to headerArea (superarea). This means, after each headerArea, the linesArea will be printed.
  4. The field TO (KEY) is the name of the field/s in the subtable (linesTable)
  5. The field FROM (KEY) is the name of the field/s in the supertable (headerTable). You can specifiy several fields separated by "|".
  6. the RDatabaseSource in linesArea must be linked to the RDatabaseSource in headerArea.

You can also use parameters in your SQL statement. For example:

sta1.CommandText="SELECT * FROM INVOICES where IDate>'[%dateParam]'";
RDatabaseSource mySource=new RDatabaseSource(con1,sta1);

in this case you must provide a value for the parameter before you run the report:

mySource.setParameter("dateParam","01/01/2001");

 

 

Creating DHTML

RReport can also export your report to DHTML. This is usefull if you are using rreport in a web environment.

In order to export to DHTML you must call the following methods:


[c#]

rep.setDHTMLActive(true); // select DHTML mode
rep.disablePrinting(true); // do not send output to printer

/ / print report now
rep.prepare();
....
rep.endReport();

// get DHTML output
string htmlString=rep.getHTML();

[vbnet]
rep.setDHTMLActive(true) ' select DHTML mode

rep.disablePrinting(true)

rep.prepare()
...
rep.endReport()

' get dthml output
dim htmlString as string
htmlString= rep.getHTML()

 

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:

[c#]

report.exportImagesFormat="png"; // store the chart or barcode as png 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 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 generate <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.

 

Creating PDF

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 PDF you must call the following methods:

[c#]
rep.disablePrinting(true); // do not send output to printer

/ / print report now
rep.prepare();
....
rep.endReport();

rep.exportPDF("output.pdf"); // set pdf output file

[vbnet]

rep.disablePrinting(true)

' print report now
rep.prepare()
...
rep.endReport()
rep.exportPDF("report.pdf")

RReport uses a free J# library called iText that creates PDF files. You will need version 1.00-1b, Click here to download the pdf library. If the link is not working let us know and we will send you the library per email.

You must install the PDF library by including the reference iTextdotNET.dll , JSharpLib.dll in your project (zlib.dll must be in the same directory). You will also need the J# redistributable package (available from Micorosft's web site) and you will have to add a reference to vjscor.dll and vjslib.dll.

The class PDFLayer is in charge of converting your report to PDF using iText.

Note 1: if you try to create a PDF file in a Web application (aspx file), you must make sure you provide the correct path in the exportPDF() method. If you do not provide the path you can't be sure where the file will be created (sometimes in /windows/system32 which is not allowed). Furthermore the web server normally requires you to create the file in the web directory or subdirectory, otherwise it will fail.

Note 2: If you get the following error while opening the generated pdf file:

illegal operation 'BT' inside a text object

You must check you have copied the iText fonts and hyph subdirectories in your application's working directory.

Web Reports (aspx pages)

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.

Creating DHTML output in a aspx page:

<%@ Page language="VB" AutoEventWireup="false" Trace="true" Debug="true" %>
<%@Import Namespace="System.Drawing" %>
<%@Import Namespace="System.IO" %>
<%@Import Namespace="System.Drawing.Imaging" %>
<%@Import Namespace="J4L.RReport" %>
<%@ OutputCache Duration="100" VaryByParam="none" %>
<%
' load report from file
Dim report as Report

report=new Report()

if (not report.importReport("c:\j4l\RReportNET\examples\DatabaseSource\DBorder.rep")) then
Console.WriteLine("Error, exiting")
end if

' create preview window
Dim Win as RReportWindow

report.setDHTMLActive(true)
report.disablePrinting(true)

' this will print the Header Area and all dependent areas
report.prepare()
report.endReport()

dim htmlString as string
htmlString= report.getHTML()

Response.ClearContent()
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.Write(htmlString)
Response.End()
%>

Creating PDF output in a aspx page:

<%@ Page language="VB" AutoEventWireup="false" Trace="true" Debug="true" %>
<%@Import Namespace="System.Drawing" %>
<%@Import Namespace="System.IO" %>
<%@Import Namespace="System.Drawing.Imaging" %>
<%@Import Namespace="J4L.RReport" %>
<%@ OutputCache Duration="100" VaryByParam="none" %>
<%

' load report from file
Dim report as Report

report=new Report()


if (not report.importReport("c:\j4l\RReportNET\examples\DatabaseSource\DBorder.rep")) then
Console.WriteLine("Error, exiting")
end if

' create preview window
Dim Win as RReportWindow

report.setDHTMLActive(false)
report.disablePrinting(true)
report.setPDFFile("report.pdf")
' this will print the Header Area and all dependent areas
report.prepare()
report.endReport()

Response.ClearContent()
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = "application/pdf"
Response.Redirect("report.pdf")
Response.End()
%>


Examples

You will find the following examples shipped with the product:

Note: you will need to modify the connection string of the examples DBOrder*.rep since they point to "c:\j4l\ReportVD\RReport2.mdb".

 

Text wrapping

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:

 

Grids and frames

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(1, 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(1 , 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(1, 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(1,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(1,Color.Black,RLineStyle.LINE_NORMAL));

MyRJTable.SetLINFrameStyle(new RLineStyle(1,Color.Black,RLineStyle.LINE_NORMAL));

MyRJTable.SetLINGridFrameStyle(new RLineStyle(1,Color.Black,RLineStyle.LINE_NORMAL));

To create frames and grid for the table.