Source code for a simple .NET report application
This simplified .NET report program shows you the basic C# code you would need to create a .NET report application.
This C# program completes the basic needs for any Genero Report Writer program:
- Creates the data model.
- Loads the data into memory.
- Configures the output of the report.
- Streams the data to the report engine.
The report is a simple example of a C# report program. In a real world situation, the data would be read from another source, and an iterator would read the data into memory and into the data stream one record at a time.
using FourJs.Report.Runtime; using System; using System.Collections.Generic; using System.Xml.Serialization; namespace Sales { //The XmlRoot annotation causes an global element declaration to be produced in the schema. [Serializable] [XmlRoot] public class Sales { //The XmlElement annotation maps a property to an XML element. //The Genero Engine does not support optional variables so setting "IsNullable = true" is mandatory. //If a variable needs to be optional then set the variable to null whenthere is no value. //If a primitive type needs to be optional then use the c# nullable type //instead (e.g "int?" for "int"). [XmlElementAttribute(IsNullable = true)] public String shopName; public int zipCode; public DateTime day; //This and any other public collection will be serialized in the order they are declared descending //recursively into the classes contained in the collections. [XmlElementAttribute(IsNullable = true)] public List<SalesItem> items; public Sales(String shopName, int zipCode, DateTime day) { this.items = new List<SalesItem>(); this.shopName = shopName; this.zipCode = zipCode; this.day = day; int i = 0; items.Add(new SalesItem("Tablelamp", SalesItem.Category.Furniture, 23.00, null)); items.Add(new SalesItem("Tablelamp", SalesItem.Category.Furniture, 267.00, items[i++])); items.Add(new SalesItem("Officechair", SalesItem.Category.Furniture, 155.00, items[i++])); items.Add(new SalesItem("Grandfather clock", SalesItem.Category.Furniture, 329.00, items[i++])); items.Add(new SalesItem("Scissors", SalesItem.Category.Supplies, 19.00, items[i++])); items.Add(new SalesItem("Measuring tape", SalesItem.Category.Supplies, 23.00, items[i++])); items.Add(new SalesItem("Sunglasses", SalesItem.Category.Travelling, 15.95, items[i++])); items.Add(new SalesItem("Penknife", SalesItem.Category.Travelling, 6.25, items[i++])); items.Add(new SalesItem("Ornateangel", SalesItem.Category.Art, 1.95, items[i++])); } /** Default Constructor that is required for deserialization. In this program this is never used. */ public Sales() { } /** Runs the report using the design file specified in args[0] or "SalesList.4rp" otherwise. The program creates the file "SalesList.pdf" and opens it using System.Diagnostics.Process.Start which will typically invoke the Acrobat Reader. */ static void Main(string[] args) { String designFile; String outputFilename = "SalesList.pdf"; if (args.Length == 0) { designFile = "..\\SalesList.4rp"; } else { designFile = args[0]; } FormatHandler handler = new FormatWriter(outputFilename); PDFRenderer renderer = new PDFRenderer(handler); FourRpLayouter report = new FourRpLayouter(designFile, renderer); report.debugLevel = 9; Sales data = new Sales("Columbus Arts", 75038, new DateTime()); report.runFromSerializable(data); // open the file System.Diagnostics.Process.Start(outputFilename); } } public class SalesItem { public enum Category { Furniture, Art, Supplies, Travelling }; [XmlElementAttribute(IsNullable = true)] public String articleName; public Category category; public double price; public double runningTotal; //The previous item is passed to allow computing the running total. public SalesItem(String articleName, Category category, double price, SalesItem previousItem) { this.articleName = articleName; this.category = category; this.price = price; this.runningTotal = previousItem == null ? price : previousItem.runningTotal + price; } /** Default Constructor that is required for deserialization. In this program this is never used. */ public SalesItem() { } } }
An overview of the simple report
public class Sales
- whereSales
represents the sales of a particular shop on a particular day.Public class SalesItem
- whereSalesItem
represents the individual items sold in the shop on that day.
The classes are not required to implement any specific interfaces or to be extensions of a specific class. These classes are annotated to hint to the serializer how these objects are to be serialized to XML.
- The Report Model Objects, which specify the data the report will include.
- A
main
method to run the report using a simple list design and to view the result in PDF format.
Using this API is the method proposed in this example.
Mandatory C# classes to be imported
using FourJs.Report.Runtime;
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
XML annotations
Serializable
- The
Serializable
annotation marks classes that should be serialized.[Serializable]
XmlRoot
- The
XmlRoot
annotation causes a global element declaration to be produced in the schema.... [XmlRoot] public class Sales { ...
XmlElementAttribute
- The
XmlElementAttribute
annotation maps a property to an XML element.[XmlElementAttribute(IsNullable = true)] public String shopName;
Note: The Genero Report Engine does not support optional values. If a variable needs to be optional, use "isNullable=true
" and set the variable to null when there is no value.
Genero Report Writer APIs and C# code highlights
- Use a handler
object.
FormatHandler handler = new FormatWriter(outputFilename);
- Define a renderer according to the expected output format. In this example, the
PDFRenderer
is specified. See Change report output format (C#) for a summary of your choices.PDFRenderer renderer = new PDFRenderer(handler);
- Create the report object specifying the report design file and the renderer
object.
FourRpLayouter report = new FourRpLayouter(designFile, renderer);
- Specify the data.
Sales data = new Sales("Columbus Arts", 75038, new DateTime());
- Run the report.
report.runFromSerializable(data);
The following is an alternative method for running a report, using a data file (.xml) instead of a database.
In our simple program, no iterator is specified. All the data is in memory, and the standard iterator goes through that list in memory, done internally by
runFromSerializable
. To see code that uses an iterator, examine the code in the OrderReportCSharp demo.report.runFromXML("my_data_file.xml");
- Generate the report file on
disk.
File result = new File(outputFilename);