How to create a single pdf containing multiple invoices - jasper-reports

I feed an xml file to JasperReports in order to generate a single invoice. This works fine.
However, I would also like to generate multiple invoices (i.e. all invoices for a given user) from a single xml file. The output should be just a single pdf file.
The XML file looks like this
<orders>
<order>
...
</order>
<order>
...
</order>
<order>
...
</order>
</orders>
Is this possible with JasperReports by just editing the jrxml file? I know that I could generate a pdf for each invoice by calling JasperReports in a loop. But I'd like to avoid this since it would require modifing a lot of code.
Update
I use the Jasper-Rails plugin for RoR to generate the reports. https://github.com/fortesinformatica/jasper-rails/blob/master/lib/jasper-rails/jasper_reports_renderer.rb
An xml for a single invoice is simply <order> ... </order>
The jrxml (note: xPath has already been changed to reflect mkl's approach) http://pastebin.com/R0vnrQgU

It is possible to generate a single PDF with multiple invoices if it before was possible to generate a PDF for a single invoice.
It is not clear how many changes to the JRXML are required. Unfortunately the OP did not provide a JRXML. To illustrate a simple case:
If the order merely contains some static amount of data and the JRXML, therefore, only essentially works on one data set, there is hardly anything to change. e.g.:
Let's assume you have original XMLs similar to this sample:
<order>
<name>Mr. Smith</name>
<quantity>2</quantity>
<item>bike</item>
<price>200</price>
</order>
and an original JRXML similar to this sample:
<queryString language="xPath">
<![CDATA[/order]]>
</queryString>
<field name="name" class="java.lang.String">
<fieldDescription><![CDATA[name]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.String">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="item" class="java.lang.String">
<fieldDescription><![CDATA[item]]></fieldDescription>
</field>
<field name="price" class="java.lang.String">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<variable name="aggregated" class="java.lang.Number">
<variableExpression><![CDATA[java.lang.Integer.parseInt($F{quantity}) * java.lang.Float.parseFloat($F{price})]]></variableExpression>
</variable>
<detail>
<band height="125" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="535" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Dear " + $F{name} + ","]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="40" width="235" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{item}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="335" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="75" width="535" height="35"/>
<textElement/>
<textFieldExpression><![CDATA["Please pay " + $V{aggregated} + " soon."]]></textFieldExpression>
</textField>
<textField>
<reportElement x="435" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$V{aggregated}]]></textFieldExpression>
</textField>
</band>
</detail>
Now for multi-invoice XMLs like this sample:
<orders>
<order>
<name>Mr. Smith</name>
<quantity>2</quantity>
<item>bike</item>
<price>200</price>
</order>
<order>
<name>Mr. Fisher</name>
<quantity>3</quantity>
<item>box</item>
<price>10</price>
</order>
</orders>
all you have to do in the JRXML is to change the xPath expression to match all order elements and add a page break between data sets:
...
<queryString language="xPath">
<![CDATA[//order]]>
</queryString>
...
<detail>
<band height="125" splitType="Stretch">
...
<break>
<reportElement x="0" y="124" width="535" height="1"/>
</break>
</band>
</detail>
Even if the order contains more dynamic data, e.g. a variable number of items, it might be just as easy as long as the order element defines the main data set (the variable number of items might be handled by some table element working on a subdataset).
Update
After the OP provided his JRXML file, it turns out that it essentially is of the simple type indicated above. A small correction is required, though:
The OP's JRXML uses only two sections, Title and Page Footer. The latter indeed is used for page footer material but the former is not used for a title but instead for the actual invoice body, i.e. for material which shall be printed not once (as a title) but as many times as there are data sets! To make this ready for multi-invoice outputs, therefore, the title band first has to be moved to become a detail band:
...
</background>
<title>
<band height="616" splitType="Stretch">
...
</band>
</title>
<pageFooter>
...
becomes
...
</background>
<detail>
<band height="616" splitType="Stretch">
...
</band>
</detail>
<pageFooter>
...
And due to the sheer size of this band, this already suffices to make the JRXML ready for multi-order inputs: A page break occurs automatically before the next detail section with information for the next data set because not more than one of these bands fits on a page and the band splitType is "Stretch".

The output into a single pdf isn't the point.
The key is how to use page breaks for each invoice and the use of the headers/bands, I think.

Related

iReport variable expression returns null

Here's the simple code in XML view of print form:
<variable name="TITLE" class="java.lang.String">
<variableExpression><![CDATA[$F{APP_NUMBER}.replaceAll( "app_", "" )]]></variableExpression>
</variable>
If I use this variable in form, it returns null (while using "$V{TITLE}"). But if I remove replaceAll method, it works and returns correct value.
What is wrong with expression? Should I use something instead of "<variableExpression>"?
If you are printing this variable in Title band change its evaluation time to "Report"
<title>
<band height="79" splitType="Stretch">
**<textField evaluationTime="Report">**
<reportElement x="143" y="43" width="100" height="30" uuid="4fc0ce80-ced5-448e-bdd1-1571b3bc788f"/>
<textFieldExpression><![CDATA[$V{TITLE}]]></textFieldExpression>
</textField>
</band>
</title>

Comparing two columns on a row and removing if they match

I'm looking to create a report in iReport, this will display a row of Car weights which includes there expected weight and actual weight. I'm looking to only display the cars that have are different between the actual weight and expected weight. I'm also looking to display an extra columns on the right which displays how much they're different by.
E.g.
CAR Expected Weight ActualWeight WeightDIFF
-------------------------------------------
> NUGLN9L 2000kg 2200kg 200kg
> YBOL9GT 1700kg 1700kg 0kg (Shouldn't display this row)
> CL55GBP 1100kg 2200kg 1100kg
The part of jrxml:
<columnHeader>
<band height="61" splitType="Stretch">
<textField>
<reportElement x="108" y="0" width="100" height="20" uuid="205a44be-528a-4d6b-83e7-85cc0f417fd6"/>
<textFieldExpression><![CDATA[$F{car}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="219" y="0" width="100" height="20" uuid="704e546a-d4f1-4d8d-b5e7-a7ac8154d882"/>
<textFieldExpression><![CDATA[$F{expectedWeight}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="332" y="0" width="100" height="20" uuid="08846a54-7415-4f32-a0ef-41f2770e2278"/>
<textFieldExpression><![CDATA[$F{ActualWeight}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="443" y="0" width="100" height="20" uuid="7ebea114-3303-48c0-b877-f0940c62aa7f"/>
<textFieldExpression><![CDATA[$F{WeightDIFF}]]></textFieldExpression>
</textField>
</band>
</columnHeader>
Any help would be excellent
If you are using iReport designer you can select the field on screen, on the right pane of properties each field has a Print When Expression property. You can create a variable (Boolean is easiest). E.G
!$F{CarWeight1}.equals($F{CarWeight2})
Create a variable and set that as a boolean. Drop the variable into the print when expression property on each field. Also worth ticking remove line when blank for each field for formatting purposes.
Hope this helps.
As #AlexK pointed out, you can use the Print when expression.
After your <band> row, add the following (I assume $F{WeightDIFF} is an Integer):
<printWhenExpression><![CDATA[$F{WeightDIFF} > 0]]></printWhenExpression>

Nested Tags in JasperReports

I have an XML File that looks like this:
<?xml version="1.0" encoding="utf-8"?><template>
<Kinder>
<vorname>Kevin</vorname>
<zuname>Müller</zuname>
<geburtsdatum>21.01.2010</geburtsdatum>
<Kontakt>
<typ>Vater</typ>
<vorname>Peter</vorname>
<zuname>Müller</zuname>
</Kontakt>
<Kontakt>
<typ>Mutter</typ>
<vorname>Petra</vorname>
<zuname>Müller</zuname>
</Kontakt>
</Kinder>
<Kinder>
<vorname>Schakkeline</vorname>
<zuname>Meyer</zuname>
<geburtsdatum>21.03.2011</geburtsdatum>
<Kontakt>
<typ>Mutter</typ>
<vorname>Maria</vorname>
<zuname>Meyer</zuname>
</Kontakt>
</Kinder>
</template>
I want to print this in a ways that the structure is kept, like this:
Kevin Müller 21.01.2010
Peter Müller
Petra Müller
Schakkeline Meyer 21.03.2011
Maria Meyer
the main lines I get like this:
<queryString language="xPath">
<![CDATA[/template/Kinder]]>
</queryString>
<field name="zuname" class="java.lang.String">
<fieldDescription><![CDATA[zuname]]></fieldDescription>
</field>
<field name="vorname" class="java.lang.String">
<fieldDescription><![CDATA[vorname]]></fieldDescription>
</field>
...
<band height="102" splitType="Stretch">
<textField>
<reportElement x="32" y="34" width="136" height="16" uuid="403ac891-da84-444e-a7f1-33aef84483fa"/>
<textFieldExpression><![CDATA[$F{vorname}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="32" y="14" width="100" height="20" uuid="670d9156-6282-4b53-9268-275457f07ce0"/>
<textFieldExpression><![CDATA[$F{zuname}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="179" y="14" width="100" height="20" uuid="b7356c70-e27c-48a7-be46-e39400da4c1f"/>
<textFieldExpression><![CDATA[$F{geburtsdatum}]]></textFieldExpression>
</textField>
But how do I access the nested tags like
<Kontakt>
<typ>Vater</typ>
<vorname>Peter</vorname>
<zuname>Müller</zuname>
</Kontakt>
?
I mean something like a for-loop, in a way that I can iterate over as many subtags as exist.
You can use subreport with datasource query like "//Kontakt"
<dataSourceExpression><![CDATA[
((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("//Kontakt")
]]></dataSourceExpression>
example here community.jaspersoft.com/questions/524978/empty-subreport-xml-datasource-ireport

iReport pageHeader Image issue

I am using iReport 3.0.0 , presently trying to make a simple change replace image inside a pageHeader with another , but the issue is the new image doesnt fit in.
The band height is 100
old image is png format, 217 x 132 ,and it is inside image element width="190" height="70" ( and this worked fine )
new image is png format, 192 x 130 and is inside image element width="103" height="100"
The issue is for new image there is a v small portion of the image in bottom is not showing up , i changed the height from 70 to 100 , still the same issue.
Any pointers appreciated
OLD CODE IS
<pageHeader>
<band height="100" isSplitAllowed="true" >
<image evaluationTime="Now" hyperlinkType="None" hyperlinkTarget="Self" >
<reportElement x="0" y="12" width="190" height="70" key="image-2"/>
<box></box>
<graphicElement stretchType="NoStretch"/>
<imageExpression class="java.lang.String"><![CDATA[$P{REPORT_BASE_DIR}+"Old_logo.png"]]></imageExpression>
</image>
</band>
</pageHeader>
NEW Code IS
<pageHeader>
<band height="100" isSplitAllowed="true" >
<image evaluationTime="Now" hyperlinkType="None" hyperlinkTarget="Self" >
<reportElement x="379" y="0" width="103" height="100" key="image-2"/>
<box></box>
<graphicElement stretchType="NoStretch"/>
<imageExpression class="java.lang.String"><![CDATA[$P{REPORT_BASE_DIR}+"New_Logo.png"]]></imageExpression>
</image>
What am i doing wrong ??
Whats is your ireport version?
I tried it with the examples that IDE provides :
Example 1: https://gist.github.com/64fbf51838e648c28a76.git
<image>
<reportElement x="2" y="0" width="118" height="132"/>
<imageExpression><![CDATA["tree1.png"]]></imageExpression>
</image>
Example 2: https://gist.github.com/1a97fa35e63cabb2f8e7.git
<image>
<reportElement x="275" y="0" width="300" height="64"/>
<imageExpression><![CDATA["leaf_banner_red.png"]]></imageExpression>
</image>
I think is your <box> tag or something diferent to this examples.

Grouping records in JasperReports

I have a problem with JasperReports. I want to group the records depending on one specific column's value.
For example input data:
Name--email--PledgeType--amount
aaa--aa#yahoo.com--1--20.00
bbb--bb#yahoo.com--2--30.00
ccc--cc#gmai.com--1--35.00
ddd--dd#gmai.com--2-- 40.00
The output report will be grouped by the "PledgeType" value (1, 2, ... number):
Total for group one: 55.00
Name email amount
aaa aa#yahoo.com 20.00
ccc cc#gmai.com 35.00
------------------------------------
Total for group two: 70.00
Name email amount
bbb bb#yahoo.com 30.00
ddd dd#gmai.com 40.00
Can JasperReports solve this problem? how?
You can define grouping in JasperReports. JasperReports calculates the total for you, there is comfortable way to add groups and totals. Here an overview what you need to do in iReport.
To add the group
modify your query to order by pledgeType - JasperReports requires the data sorted according to your grouping.
right click on the report in the report inspector and choose Add Report Group.
Follow the wizard, set as group name PledgeType and choose Group by the following report object where you select the field PledgeType. Click next. Check Add the group header and click Finish.
To add the total
right click on variables in the report inspector and choose Add Variable.
In the properties panel choose this configuration: Variable class: BigDecimal, Calculation: Sum, ResetType: Group, ResetGroup PledgeType, Variable Expression: $F{amount}.
Drag & drop the variable into the group header in the report designer. Click on the field and change: Text field expression: "Total for group " + $F{PledgeType} + ": " + $V{totalPledge}, Expression Class: java.lang.String. Evaluation time: Group. Evaluation Group: PledgeType.
Info: The evaluation time decides when a variable gets evaluated, i.e. when the sum of the calculation will be shown. If you set it to group it means 'once the group processing is completed'.
Attached the generated report and the JRXML.
The JRXML is created with iReport 5.0 - however, if you follow the steps above it should work with JR v 2+
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report2" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ce08fe1c-1543-4460-8613-7f03b200082b">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<queryString>
<![CDATA[select * from
(select 'aaa' as Name, 'aa#yahoo.com' as email, 1 as PledgeType, 20.00 as amount
union select 'bbb', 'bb#yahoo.com' ,2, 30.00
union select 'ccc', 'cc#gmai.com' ,1, 35.00
union select 'ddd', 'dd#gmai.com' ,2, 40.00) tbl
order by PledgeType]]>
</queryString>
<field name="Name" class="java.lang.String"/>
<field name="email" class="java.lang.String"/>
<field name="PledgeType" class="java.lang.Long"/>
<field name="amount" class="java.math.BigDecimal"/>
<variable name="totalPledge" class="java.math.BigDecimal" resetType="Group" resetGroup="PledgeType" calculation="Sum">
<variableExpression><![CDATA[$F{amount}]]></variableExpression>
</variable>
<group name="PledgeType">
<groupExpression><![CDATA[$F{PledgeType}]]></groupExpression>
<groupHeader>
<band height="61">
<textField evaluationTime="Group" evaluationGroup="PledgeType">
<reportElement uuid="401c7b3b-af73-4d40-8982-9c1692eb7085" x="0" y="21" width="555" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Total for group " + $F{PledgeType} + ": " + $V{totalPledge}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="87cd0d21-014d-4e6c-a54a-006165a38414" x="0" y="41" width="185" height="20"/>
<textElement/>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement uuid="bd0fc2f5-4963-4c9d-a9be-3659be06e436" x="185" y="41" width="185" height="20"/>
<textElement/>
<text><![CDATA[email]]></text>
</staticText>
<staticText>
<reportElement uuid="5d5d7ce1-5353-4f83-91b4-57725b0c922b" x="370" y="41" width="185" height="20"/>
<textElement/>
<text><![CDATA[amount]]></text>
</staticText>
</band>
</groupHeader>
</group>
<detail>
<band height="20">
<textField>
<reportElement uuid="5b325da6-7c56-4357-8808-911dad16ec53" x="0" y="0" width="185" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{Name}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="0bc06b28-7b8c-4af9-997a-714d1599def1" x="185" y="0" width="185" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="e5504bb9-c3c0-4135-94c6-7ea935f97cb6" x="370" y="0" width="185" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{amount}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>