Architecture
A schematic diagram of Genero Report Writer for Swift
Scalability
A schematic diagram illustrating the distributed nature of Genero Report Writer for Swift
Detailed feature overview
Customizing the presentation
Data production and presentation separated
Structured data source
Performance & scalability
Sophisticated layout engine
APIs
Report viewers and devices
Run time localization
Templates
Maintenance
Data source generation
Database support
All of the industry’s leading databases are supported:
Schema written by hand
Graphical reports are designed based on a XML schema that matches the data to be serialized.
Write your schema by hand.
The schema for the sample program reads as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="sales" type="sales"></xs:element> <xs:complexType name="sales"> <xs:sequence> <xs:element name="shopName" type="xs:string" nillable="true"></xs:element> <xs:element name="zipCode" type="xs:int"></xs:element> <xs:element name="day" type="xs:dateTime" nillable="true"></xs:element> <xs:element name="items" type="salesItem" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="salesItem"> <xs:sequence> <xs:element name="articleName" type="xs:string" nillable="true"></xs:element> <xs:element name="category" type="category" nillable="true"></xs:element> <xs:element name="price" type="xs:double"></xs:element> <xs:element name="runningTotal" type="xs:double"></xs:element> </xs:sequence> </xs:complexType> <xs:simpleType name="category"> <xs:restriction base="xs:string"> <xs:enumeration value="Furniture"></xs:enumeration> <xs:enumeration value="Art"></xs:enumeration> <xs:enumeration value="Supplies"></xs:enumeration> <xs:enumeration value="Travelling"></xs:enumeration> </xs:restriction> </xs:simpleType> </xs:schema>
Run report
Select report design
if CommandLine.argc == 1 { designFile = "SalesList.4rp" } else { designFile = CommandLine.arguments[1] }
Configure the output
Select PDF output
selectDevice (rcPtr, PDF)
Serialize model
let reportLauncher = Sales(content_handler, "Columbus Arts", 75038, Date())
Find below the complete listing of the SWIFT program:
/* * FOURJS_START_COPYRIGHT(U,2016) * Property of Four Js* * (c) Copyright Four Js 2016, 2017. All Rights Reserved. * * Trademark of Four Js Development Tools Europe Ltd * in the United States and elsewhere * * Four Js and its suppliers do not warrant or guarantee that these samples are * accurate and suitable for your purposes. * Their inclusion is purely for information purposes only. * FOURJS_END_COPYRIGHT */ import Foundation import libgre import AppKit public class Sales { public var content_handler: UnsafeMutablePointer var shopName: String? var zipCode: Int var day: Date? var items = [SalesItem]() public init?(_ content_handler: UnsafeMutablePointer, _ shopName: String?, _ zipCode: Int, _ day: Date?) { self.content_handler = content_handler self.shopName = shopName self.zipCode = zipCode self.day = day self.items.append(SalesItem("Tablelamp", SalesItem.Category.Furniture, 23.00, nil)); self.items.append(SalesItem("Tablelamp", SalesItem.Category.Furniture, 267.00, self.items.last)); self.items.append(SalesItem("Officechair", SalesItem.Category.Furniture, 155.00, self.items.last)); self.items.append(SalesItem("Grandfather clock", SalesItem.Category.Furniture, 329.00, self.items.last)); self.items.append(SalesItem("Scissors", SalesItem.Category.Supplies, 19.00, self.items.last)); self.items.append(SalesItem("Measuring tape", SalesItem.Category.Supplies, 23.00, self.items.last)); self.items.append(SalesItem("Sunglasses", SalesItem.Category.Travelling, 15.95, self.items.last)); self.items.append(SalesItem("Penknife", SalesItem.Category.Travelling, 6.25, self.items.last)); self.items.append(SalesItem("Ornateangel", SalesItem.Category.Art, 1.95, self.items.last)); self.serializeToXML() } public func serializeToXML() { startElement(content_handler, "sales") addElement(content_handler, "shopName", shopName) addElement(content_handler, "zipCode", "(zipCode)") addElement(content_handler, "day", (day == nil ? nil : "(day!)")) for item in items { item.serializeToXML(content_handler) } endElement(content_handler, "sales") } class SalesItem { enum Category: String { case Furniture, Art, Supplies, Travelling } var articleName: String? var category: Category? var price: Double var runningTotal: Double // The previous item is passed to allow computing the running total. init(_ articleName: String?, _ category: Category?, _ price: Double, _ previousItem: SalesItem?) { self.articleName = articleName self.category = category self.price = price self.runningTotal = (previousItem == nil ? price : previousItem!.runningTotal + price) } func serializeToXML(_ content_handler: UnsafeMutablePointer) { startElement(content_handler, "items") addElement(content_handler, "articleName", articleName) addElement(content_handler, "category", (category == nil ? nil : category!.rawValue)) addElement(content_handler, "price", "(price)") addElement(content_handler, "runningTotal", "(runningTotal)") endElement(content_handler, "items") } } } public func addElement(_ content_handler: UnsafeMutablePointer, _ name: String, _ content: String?) { if (content == nil) { startElement(content_handler, name) attribute(content_handler, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") attribute(content_handler, "xsi:nil", "true") endElement (content_handler, name) } else { startElement(content_handler, name) characters(content_handler, content!) endElement (content_handler, name) } } /** * MAIN * * 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 * NSWorkspace.shared().open() which will typically * invoke the Preview application. */ var designFile: String var outputFilename: String = "SalesList.pdf" if CommandLine.argc == 1 { designFile = "SalesList.4rp" } else { designFile = CommandLine.arguments[1] } let rcPtr = createRuntimeConfiguration(designFile) setOutputFileName(rcPtr, outputFilename) selectDevice (rcPtr, PDF) configureDistributedProcessing(rcPtr, "127.0.0.1", 7000) guard let content_handler = createContentHandler(rcPtr) else { print("Info: Report Writer server may not be started. Launch it with the following command: greportwriter -l 7000") exit(EXIT_FAILURE) } let reportLauncher = Sales(content_handler, "Columbus Arts", 75038, Date()) // Open the file let reportFileURL = URL(fileURLWithPath: "../" + outputFilename).absoluteURL guard NSWorkspace.shared().open(reportFileURL) else { print("Error opening (outputFilename).") exit(EXIT_FAILURE) } exit(EXIT_SUCCESS)