I am trying to fill a table by passing a custom data source to it.
I have created a simple report with a table on it. The report it self gets the data from a ms sql database. I have written a java class similar to the class in this Example. But I get no value in table. At the example there is no scriptlet. I have checked the (String) this.getFieldValue("KN_FormelGG"); line of code. It gets the data from field and can show it on report. So I guess the bean data source is not filled. I call the fill Table method in a afterGroupInit. How can I use Collection of data from java in jasper? I tried also adding the java bean in dataset and query dialog, but it did not help me either. Should I add the scriptlet to subreport/table? The main emphasis of my problem having the custom data source in a scriptlet. I went the other problem through, but I still get no answer. I added $P{FieldDataSource}.getData() to check the data, but it delivers null.
java class 1:
package testProjektIman.scriptlets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
public class FillTable extends JRDefaultScriptlet {
#Override
public void afterGroupInit(final String id)
throws JRScriptletException {
fillTable();
}
public ArrayList<String> splitGGArray(final String kNFormelGG) {
ArrayList<String> fieldNames = new ArrayList<>();
String[] array = (kNFormelGG.split(" "));
for (String sub : array) {
fieldNames.add(sub);
}
return fieldNames;
}
public Map<String, Object> fillTable()
throws JRScriptletException {
String kNFormelGG = null;
kNFormelGG = (String) this.getFieldValue("KN_FormelGG");
List<TableCells> listTableCells = new ArrayList<>();
TableCells tableCell;
for (String fn : splitGGArray(kNFormelGG)) {
tableCell = new TableCells();
tableCell.setFieldName(fn);
listTableCells.add(tableCell);
}
JRBeanCollectionDataSource tableCellJRBean = new JRBeanCollectionDataSource(listTableCells);
Map<String, Object> parameters = new HashMap<>();
parameters.put("FieldDataSource", tableCellJRBean);
return parameters;
}
}
Java class 2
package testProjektIman.scriptlets;
public class TableCells {
private String fieldName;
private String keyFormel;
private String mK;
private String notation;
private String Item;
//getters setters
}
jrxml
<?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="tableAutoFill" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="37fc3a9c-38e9-41be-9039-56249c5283d7">
<subDataset name="TableDataSource" uuid="5999e646-aeec-4b2b-b29b-68e897d56999">
<queryString>
<![CDATA[]]>
</queryString>
<field name="fieldName" class="java.lang.String"/>
</subDataset>
<scriptlet name="Filltable" class="testProjektIman.scriptlets.FillTable"/>
<parameter name="FieldDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource" isForPrompting="false"/>
<queryString>
<![CDATA[select * from "KennzahlReferenz2015_QIBericht", "Images"
where LB_ID = 62
and KN_OffiziellGruppe = 3
and IMG_ID = 1]]>
</queryString>
<field name="KN_Id" class="java.lang.Integer"/>
<field name="KN_FormelZ" class="java.lang.String"/>
<field name="KN_FormelGG" class="java.lang.String"/>
<group name="id">
<groupExpression><![CDATA[$F{KN_Id}]]></groupExpression>
<groupHeader>
<band height="50"/>
</groupHeader>
<groupFooter>
<band height="50"/>
</groupFooter>
</group>
<detail>
<band height="191" splitType="Stretch">
<componentElement>
<reportElement x="50" y="18" width="260" height="120" uuid="942ab836-df83-4a2f-8215-845073ad163f">
<property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
<property name="com.jaspersoft.studio.table.style.table_header" value="Table_TH"/>
<property name="com.jaspersoft.studio.table.style.column_header" value="Table_CH"/>
<property name="com.jaspersoft.studio.table.style.detail" value="Table_TD"/>
</reportElement>
<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" whenNoDataType="AllSectionsNoDetail">
<datasetRun subDataset="TableDataSource" uuid="b554ada5-c388-4534-af8e-93571a417adb">
<parametersMapExpression><![CDATA[$P{FieldDataSource}]]></parametersMapExpression>
<dataSourceExpression><![CDATA[$P{FieldDataSource}]]></dataSourceExpression>
</datasetRun>
<jr:column width="100" uuid="f57e4e8e-8a2e-405f-b9ab-7a704e0986fd">
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
<jr:columnHeader style="Table_CH" height="30">
<staticText>
<reportElement x="0" y="0" width="100" height="30" uuid="9a55dd73-71e3-4559-9a8b-17d98bf17753"/>
<textElement>
<font isBold="true"/>
</textElement>
<text><![CDATA[FieldName]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="Table_TD" height="30">
<textField>
<reportElement x="0" y="0" width="100" height="30" uuid="c3e6ccfc-9f91-4d7a-800a-613f5dded928"/>
<textFieldExpression><![CDATA[$F{fieldName}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
</band>
</detail>
</jasperReport>
Data Adapter
Create a data adapter file, for example adapter.xml, through the user interface. The contents might resemble:
<?xml version="1.0" encoding="UTF-8" ?>
<beanDataAdapter class="net.sf.jasperreports.data.bean.BeanDataAdapterImpl">
<name>YourClass</name>
<factoryClass>com.yourcompany.jasper.JRDataSourceFactory</factoryClass>
<methodName>createCollection</methodName>
<useFieldDescription>false</useFieldDescription>
</beanDataAdapter>
Data Class
Create a class that has a createCollection method, as per the data adapter definition above:
package com.compay.jasper;
public class JRDataSourceFactory {
/**
* #return A collection of data for the report.
*/
public static Collection<YourClass> createCollection() {
return Arrays.asList( new YourClass() );
}
}
Set Report Properties
Ensure that the report has the following property (links the report to the custom data adapter):
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="adapter.xml"/>
Set Report Fields
The report fields should now be able to reference the bean properties:
<field name="yourObject.property" class="java.lang.String">
<fieldDescription><![CDATA[yourObject.property]]></fieldDescription>
</field>
It's important that the fieldDescription element contain a value that reflects the bean property (i.e., the Java code you would normally call to retrieve the value from the bean on an instance of that bean).
Application
The JRDataSourceFactory class stands alone -- it's used by the data adapter to create a collection of bean instances. The static method (createCollection) does the work here and does not, indeed cannot, use inheritance.
Example
If possible, borrow the field names for the report from the bean's attributes. The code as written in the question makes it difficult to discern where the value for KN_Id comes from.
The following example links the data adapter to the field names in the report.
Bean Class
A bean exposes some properties:
package com.company.domain;
public final class Student extends Entity {
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
Data Adapter
The data adapter looks like:
<?xml version="1.0" encoding="UTF-8" ?>
<beanDataAdapter class="net.sf.jasperreports.data.bean.BeanDataAdapterImpl">
<name>Student</name>
<factoryClass>com.company.jasper.JRDataSourceFactory</factoryClass>
<methodName>createCollection</methodName>
<useFieldDescription>false</useFieldDescription>
</beanDataAdapter>
Data Class
The data class creates instances of the bean:
package com.compay.jasper;
import com.company.domain.Student;
public class JRDataSourceFactory {
public static Collection<Student> createCollection() {
return Arrays.asList( new Student() );
}
}
Report Fields
The report fields reflect the bean fields:
<field name="firstName" class="java.lang.String">
<fieldDescription><![CDATA[firstName]]></fieldDescription>
</field>
<field name="lastName" class="java.lang.String">
<fieldDescription><![CDATA[lastName]]></fieldDescription>
</field>
A collection of "student" instances is passed into the report. In this example, the collection contains a single instance. In your example, the collection could contain many instances. As the report library iterates over the collection, different values of firstName and lastName will be made available.
The mechanics for how the Student instance data is initially populated is outside the scope of this answer. As far as the reporting tool is concerned, it simply uses pre-populated instances of Student. If FillTable populates TableCells, that's not a concern for the reporting tool.
Related
I'm trying to create a multi axis chart with one plot which shows a bar chart and another plot which shows a line chart. I found the multi axis chart to do this, but when I run my code only one plot is showing (image provided here). Any idea's on how to solve this?
In my search for a solution I came accross this post, but when I execute this it just does the same.
(When I switch the order of the barChart and lineChart in the jrxml it only shows the lineChart. Code provided below.)
Java bean
public class OperationSuccessrateBean {
private Integer week;
private Integer totalOrders;
private Double successrate;
public OperationSuccessrateBean(Integer week, Integer totalOrders, Double successrate) {
this.week = week;
this.totalOrders = totalOrders;
this.successrate = successrate;
}
public Integer getWeek() {
return week;
}
public Integer getTotalOrders() {
return totalOrders;
}
public Double getSuccessrate() {
return successrate;
}
}
Java: Filling the report
private void setOperationSuccessrate(String operationType, Map<String, Object> paramMap,
List<OperationSuccessrateBean> successrateBeans) {
paramMap.put(operationType + "_OPERATION_SUCCESSRATE_SET", new JRBeanCollectionDataSource(
successrateBeans));
paramMap.put(operationType + "_OPERATION_SUCCESSRATE_ORDERS_SET",
new JRBeanCollectionDataSource(successrateBeans));
}
jrxml: define datasets and parameters
<subDataset name="loadOperationSuccesrateSet" uuid="247b3e44-ef98-45f4-a909-e8b5678acc8f">
<field name="week" class="java.lang.Integer"/>
<field name="totalOrders" class="java.lang.Integer"/>
<field name="successrate" class="java.lang.Double"/>
</subDataset>
<subDataset name="loadOperationSuccesrateOrdersSet" uuid="247b3e44-ef98-45f4-a909-e8b5678acc8f">
<field name="week" class="java.lang.Integer"/>
<field name="totalOrders" class="java.lang.Integer"/>
<field name="successrate" class="java.lang.Double"/>
</subDataset>
<parameter name="LOAD_OPERATION_SUCCESSRATE_SET" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource" isForPrompting="false"/>
<parameter name="LOAD_OPERATION_SUCCESSRATE_ORDERS_SET" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource" isForPrompting="false"/>
jrxml: multi chart
<multiAxisChart>
<chart evaluationTime="Report">
<reportElement x="0" y="41" width="550" height="200" uuid="5078c050-dd35-43db-bf30-d04152672bd6"/>
<chartTitle/>
<chartSubtitle/>
<chartLegend/>
</chart>
<multiAxisPlot>
<plot/>
<axis position="rightOrBottom">
<lineChart>
<chart evaluationTime="Report">
<reportElement positionType="Float" x="0" y="25" width="270" height="175" backcolor="#FFFFFF" uuid="013d7a7d-2280-46d0-8d44-d537d062a182"/>
<chartTitle color="#000000"/>
<chartSubtitle color="#000000"/>
<chartLegend textColor="#000000" backgroundColor="#FFFFFF"/>
</chart>
<categoryDataset>
<dataset>
<datasetRun subDataset="loadOperationSuccesrateSet" uuid="53426928-1245-4443-97da-509b00ba1f98">
<dataSourceExpression><![CDATA[$P{LOAD_OPERATION_SUCCESSRATE_SET}]]></dataSourceExpression>
</datasetRun>
</dataset>
<categorySeries>
<seriesExpression><![CDATA["Success rate"]]></seriesExpression>
<categoryExpression><![CDATA[$F{week}]]></categoryExpression>
<valueExpression><![CDATA[$F{successrate}]]></valueExpression>
</categorySeries>
</categoryDataset>
<linePlot>
<plot/>
<categoryAxisFormat>
<axisFormat/>
</categoryAxisFormat>
<valueAxisLabelExpression><![CDATA["Success rate"]]></valueAxisLabelExpression>
<valueAxisFormat>
<axisFormat labelColor="#000000" tickLabelColor="#000000" tickLabelMask="#0%" axisLineColor="#000000">
<labelFont/>
</axisFormat>
</valueAxisFormat>
<rangeAxisMinValueExpression><![CDATA[0]]></rangeAxisMinValueExpression>
<rangeAxisMaxValueExpression><![CDATA[1]]></rangeAxisMaxValueExpression>
</linePlot>
</lineChart>
</axis>
<axis>
<barChart>
<chart evaluationTime="Report">
<reportElement x="0" y="0" width="0" height="0" backcolor="#FFFFFF" uuid="15a15c89-a2d4-4971-b4b3-1c5ac224a91e"/>
<chartTitle color="#000000"/>
<chartSubtitle color="#000000"/>
<chartLegend textColor="#000000" backgroundColor="#FFFFFF"/>
</chart>
<categoryDataset>
<dataset>
<datasetRun subDataset="loadOperationSuccesrateOrdersSet" uuid="4d001c74-1fde-47cd-b525-85d828d6ccf2">
<dataSourceExpression><![CDATA[$P{LOAD_OPERATION_SUCCESSRATE_ORDERS_SET}]]></dataSourceExpression>
</datasetRun>
</dataset>
<categorySeries>
<seriesExpression><![CDATA["TotalOrders"]]></seriesExpression>
<categoryExpression><![CDATA[$F{week}]]></categoryExpression>
<valueExpression><![CDATA[$F{totalOrders}]]></valueExpression>
</categorySeries>
</categoryDataset>
<barPlot>
<plot/>
<itemLabel/>
<categoryAxisFormat>
<axisFormat/>
</categoryAxisFormat>
<valueAxisLabelExpression><![CDATA["# Orders"]]></valueAxisLabelExpression>
<valueAxisFormat>
<axisFormat labelColor="#000000" tickLabelColor="#000000" tickLabelMask="# ##0" axisLineColor="#000000">
<labelFont/>
</axisFormat>
</valueAxisFormat>
<rangeAxisMinValueExpression><![CDATA[0]]></rangeAxisMinValueExpression>
</barPlot>
</barChart>
</axis>
</multiAxisPlot>
</multiAxisChart>
When I run my code without the multi axis chart so just to create the 2 plots next to each other it creates just fine. So I assume the data is correctely passed to the report.
The relevant libraries I use are:
net.sf.jasperreports.engine-6.4.0.jar
jfreechart-1.0.19.jar
Lorenz, I had the same issue.
The reason for the missing graph was that I was passing directly a net.sf.jasperreports.engine.data.JRBeanCollectionDataSource as parameter in the report.
Apparently for this to work you have to pass a List:
<parameter name="FIRST_DATA_SOURCE" class="java.util.List" isForPrompting="false"/>
<parameter name="SECOND_DATA_SOURCE" class="java.util.List" isForPrompting="false"/>
and then create the JRBeanCollectionDataSource inside the report:
<dataset>
<datasetRun subDataset="YOUR_SUBDATASET" uuid="a5941ba5-2088-4a31-8236-64704b54d979">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{FIRST_DATA_SOURCE})]]></dataSourceExpression>
</datasetRun>
</dataset>
In the post you referenced it was used this way and it worked!
I want to map my DataBean(TestModelA) to existing XML, but JasperReports gives me an exception. The problem is that I have custom field (TestModelB) and I have public getters and setters in that class, but jasper does not recognize them. How can i solve this problem?
TestModelA:
public class TestModelA {
private Long id;
private String label_key;
private TestModelB testModelB;
public TestModelA(Long id, String label_key, TestModelB testModelB) {
this.id = id;
this.label_key = label_key;
this.testModelB = testModelB;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLabel_key() {
return label_key;
}
public void setLabel_key(String label_key) {
this.label_key = label_key;
}
public TestModelB getTestModelB() {
return testModelB;
}
public void setTestModelB(TestModelB testModelB) {
this.testModelB = testModelB;
}
}
TestModelB:
public class TestModelB {
private Long owner;
public TestModelB(Long owner) { this.owner = owner; }
public Long getOwner() {
return owner;
}
public void setOwner(Long owner) {
this.owner = owner;
}
}
My XML file:
<?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="report3" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="077cd490-b99c-4ed1-ad76-b15714625957">
<property name="ireport.zoom" value="2.1435888100000016"/>
<property name="ireport.x" value="94"/>
<property name="ireport.y" value="0"/>
<queryString>
<![CDATA[SELECT MODULE.ID, MODULE.LABEL_KEY, MODULE.OWNER FROM MODULE]]>
</queryString>
<field name="id" class="java.lang.Long"/>
<field name="label_key" class="java.lang.String"/>
<field name="owner" class="java.lang.Long"/>
<background>
<band splitType="Stretch"/>
</background>
<columnHeader>
<band height="21" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="185" height="20" uuid="68ea9590-9d19-4bc5-9540-d059208b0ce8"/>
<text><![CDATA[id]]></text>
</staticText>
<staticText>
<reportElement x="185" y="0" width="185" height="20" uuid="325690ac-7218-4000-8ec6-a492d185477a"/>
<text><![CDATA[label_key]]></text>
</staticText>
<staticText>
<reportElement x="370" y="0" width="185" height="20" uuid="20521e4b-9057-42a9-8adc-10309abc8935"/>
<text><![CDATA[owner]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="23" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="185" height="20" uuid="11901f0e-b03d-47f8-a8aa-35bab36d26bf"/>
<textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="185" y="0" width="185" height="20" uuid="b715cb6b-3650-4266-a1cf-552ee35bc08f"/>
<textFieldExpression><![CDATA[$F{label_key}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="370" y="0" width="185" height="20" uuid="5c41b534-a74e-4b91-b35d-fcbb88789000"/>
<textFieldExpression><![CDATA[$F{owner}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
I am getting exception:
Exception in thread "main" net.sf.jasperreports.engine.JRException: Error retrieving field value from bean : owner
at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getBeanProperty(JRAbstractBeanDataSource.java:123)
at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getFieldValue(JRAbstractBeanDataSource.java:96)
at net.sf.jasperreports.engine.data.JRBeanCollectionDataSource.getFieldValue(JRBeanCollectionDataSource.java:100)
at net.sf.jasperreports.engine.fill.JRFillDataset.setOldValues(JRFillDataset.java:1330)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1231)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1207)
at net.sf.jasperreports.engine.fill.JRBaseFiller.next(JRBaseFiller.java:1554)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:149)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:909)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:841)
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:88)
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:653)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:969)
at net.didorenko.Reporter.creatReport(Reporter.java:99)
at net.didorenko.Reporter.threeReport(Reporter.java:78)
at net.didorenko.Reporter.main(Reporter.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.NoSuchMethodException: Unknown property 'owner' on class 'class net.didorenko.model.TestModelA'
at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1313)
at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:762)
at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:837)
at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:426)
at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getBeanProperty(JRAbstractBeanDataSource.java:111)
... 20 more
Your are passing TestModelA class as datasource you need either to create the method in this class or reference the method correctly from jasper report.
Solution 1 Create method in TestModelA
public Long getOwner() {
return getTestModelB().getOwner(); //Handle NullPointer?
}
Solution 2 Reference correctly in jrxml
<field name="testModelB" class="net.didorenko.model.TestModelB"/>
...
<textField>
<reportElement x="370" y="0" width="185" height="20" uuid="5c41b534-a74e-4b91-b35d-fcbb88789000"/>
<textFieldExpression><![CDATA[$F{testModelB}.getOwner()]]></textFieldExpression>
</textField>
I need to design a report to represent a pojo structure like the following:
class Obj{
field1;
field2;
List<Obj> substitutions;
}
My report will have the same field design, used one time in detail 1 band and then n-times in detail 2 with a subreport.
How can I reuse the same field design in both detail 1 and 2?
I have tryed to put a subreport in detail1 and a subreport in detail 2 pointing the same jrxml file. While the second report is ok because is filled by a collection in back object of report, I don't know how to pass current report datasource to first subreport.
Does someone have any ideas?
Here an example on the result report.
I have a pojo class named purchase.
public class Purchase {
private String name;
private String remark;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getRemark() {
return remark;
}
}
Main class to generate pdf file.
public class JasperReportIntro {
public static void main(String[] args) {
JasperReport jasperReport;
JasperPrint jasperPrint;
ArrayList<Purchase> list1 = new ArrayList<Purchase>();
ArrayList<Purchase> list2 = new ArrayList<Purchase>();
for(int i=0;i<20;i++) {
Purchase purchase = new Purchase();
purchase.setName("Vivek" + i);
purchase.setRemark("This is remark" + i);
purchase.setDiscount(10.0);
purchase.setId(i);
list1.add(purchase);
}
for(int i=0;i<20;i++) {
Purchase purchase = new Purchase();
purchase.setName("yadav" + i);
purchase.setRemark("This is remark" + i);
purchase.setDiscount(10.0);
purchase.setId(i);
list2.add(purchase);
}
try {
jasperReport = JasperCompileManager.compileReport("path/to/report.jrxml");
Map<String, List> result = new HashMap<String, List>();
JRDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(list1);
Map<String, Object> map = new HashMap<String, Object>();
map.put("dataForSubreport1",list1);
map.put("dataForSubreport2",list2);
jasperPrint = JasperFillManager.fillReport(jasperReport,map, beanCollectionDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint,
"path/to/simple_report.pdf");
System.out.println("Completed");
} catch (JRException e) {
e.printStackTrace();
}
}
}
Main report class report.jrxml.
<?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="report" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="4ddfa540-9b62-4339-9334-18733f7469cc">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
<defaultValueExpression><![CDATA["/home/jft/code/jasper-report/Genratedreports/"]]></defaultValueExpression>
</parameter>
<parameter name="dataForSubreport1" class="java.util.List"/>
<parameter name="dataForSubreport2" class="java.util.List"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="100">
<subreport>
<reportElement x="0" y="20" width="555" height="40" uuid="8798ed7b-f389-4037-9381-3862d2f3e43a"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{dataForSubreport1})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "sub1.jasper"]]></subreportExpression>
</subreport>
<subreport>
<reportElement positionType="Float" x="0" y="60" width="555" height="40" uuid="f99fdb31-afc3-4127-8148-8e0426cd71a6"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{dataForSubreport2})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "sub1.jasper"]]></subreportExpression>
</subreport>
</band>
</title>
</jasperReport>
Here is subreport sub1.jrxml.
<?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="sub1" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="48bc0742-6980-42a7-9a52-6f125fb83bc2">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<field name="name" class="java.lang.String"/>
<background>
<band splitType="Stretch"/>
</background>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20" uuid="ac3c1a86-6d0d-4b63-b339-744528573666"/>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
Download file using main class of jasperreportintro. I have passed two parameter dataForSubreport1 and dataForSubreport2 using map. and send both parameter in subreport. It use same subreport with different -2 value. Hope it will help you.
Enjoy.
When I tried to generate a report by using JavaBean Data Source and displaying the bean's field values in the table, the PDF report is showing null values.
I have a simple bean (PersonBean) as follows:
public class PersonBean {
private String Field1;
private String Field2;
public String getField1() {
return Field1;
}
public void setField1(String field1) {
Field1 = field1;
}
public String getField2() {
return Field2;
}
public void setField2(String field2) {
Field2 = field2;
}
}
The Person class which populate and return the collection of bean is as follows:
import java.util.ArrayList;
import java.util.List;
public class Person {
public static java.util.List<PersonBean> getReportData() throws Exception {
List<PersonBean> personBeanList = null;
try {
personBeanList = new ArrayList<PersonBean>();
PersonBean personBean1 = new PersonBean();
personBean1.setField1("Hina");
personBean1.setField2("Sachdev");
personBeanList.add(personBean1);
PersonBean personBean2 = new PersonBean();
personBean2.setField1("Swathi");
personBean2.setField2("Singh");
personBeanList.add(personBean2);
} catch (Exception e) {
e.printStackTrace();
}
return personBeanList;
}
}
The PersonReport class which creates report is as follows:
import java.io.FileNotFoundException;
import java.util.*;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.view.JasperViewer;
public class PersonReport implements JRDataSource {
public static void main(String[] args) throws JRException, FileNotFoundException {
try {
Map<String, Object> params = new HashMap<String, Object>();
JasperDesign jasperDesign = JRXmlLoader.load("C:/Users/sachdevh/Desktop/reports/personReport.jrxml");
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params,
new JRBeanCollectionDataSource(Person.getReportData()));
JasperExportManager.exportReportToPdfFile(jasperPrint, "./Util/bean.pdf");
JasperViewer.viewReport(jasperPrint);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Object getFieldValue(JRField arg0) throws JRException {
return null;
}
#Override
public boolean next() throws JRException {
return false;
}
}
By using iReport 4.6.0, I designed a report by inserting table component.
The jrxml file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport ..>
<subDataset name="New Dataset 1" uuid="50bff6d9-9b98-444b-9851-bdd37ea570e4">
<queryString><![CDATA[]]></queryString>
<field name="field1" class="java.lang.String">
<fieldDescription><![CDATA[field1]]></fieldDescription>
</field>
<field name="field2" class="java.lang.String">
<fieldDescription><![CDATA[field2]]></fieldDescription>
</field>
</subDataset>
<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
<defaultValueExpression><![CDATA["C:\\Users\\sachdevh\\Desktop\\reports\\"]]></defaultValueExpression>
</parameter>
<parameter name="parameter1" class="java.lang.String">
<defaultValueExpression><![CDATA[$F{field1}]]></defaultValueExpression>
</parameter>
<queryString>
<![CDATA[]]>
</queryString>
<field name="field1" class="java.lang.String">
<fieldDescription><![CDATA[field1]]></fieldDescription>
</field>
<field name="field2" class="java.lang.String">
<fieldDescription><![CDATA[field2]]></fieldDescription>
</field>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="79" splitType="Stretch"/>
</title>
<pageHeader>
<band height="35" splitType="Stretch"/>
</pageHeader>
<columnHeader>
<band height="61" splitType="Stretch">
<componentElement>
<reportElement uuid="b3e3e08d-91d9-4e01-ae74-abdfc270551a" key="table" x="0" y="0" width="555"
height="61"/>
<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
<datasetRun subDataset="New Dataset 1" uuid="f5f39e4f-4349-4e5d-9736-03f84a7a7617">
<dataSourceExpression>
<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource(Person.getReportData())]]></dataSourceExpression>
</datasetRun>
<jr:column uuid="9e2a6076-7f96-40c8-86ae-318b521a4f81" width="90">
<jr:tableHeader height="30"/>
<jr:tableFooter height="30"/>
<jr:columnHeader height="30">
<staticText>
<reportElement uuid="99411482-c1d5-44fa-aef7-9d9f4bf392ec" x="0" y="0" width="90"
height="30"/>
<textElement/>
<text><![CDATA[field1]]></text>
</staticText>
</jr:columnHeader>
<jr:columnFooter height="30"/>
<jr:detailCell height="20">
<textField>
<reportElement uuid="74861d9e-48a8-47ce-a477-81d4f497d483" x="0" y="0" width="90"
height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{field1}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column uuid="84c3b078-0114-452e-b3a3-f1c7dcd1b8cb" width="90">
<jr:tableHeader height="30"/>
<jr:tableFooter height="30"/>
<jr:columnHeader height="30">
<staticText>
<reportElement uuid="cb87f1a0-bbbf-40b2-bb19-292ecf8d9a18" x="0" y="0" width="90"
height="30"/>
<textElement/>
<text><![CDATA[field2]]></text>
</staticText>
</jr:columnHeader>
<jr:columnFooter height="30"/>
<jr:detailCell height="20">
<textField>
<reportElement uuid="84fd788f-24e8-4dfa-8c83-ce388c663f45" x="0" y="0" width="90"
height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{field2}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
</band>
</columnHeader>
<detail>
<band height="125" splitType="Stretch"/>
</detail>
<columnFooter>
<band height="45" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
<summary>
<band height="42" splitType="Stretch"/>
</summary>
</jasperReport>
I think the datasource expression below
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource(Person.getReportData())]]></dataSourceExpression>
You can solve this issue in two steps:
Move table component to the Title band (now it lies in Column Header band) - to prevent occurring of net.sf.jasperreports.engine.JRRuntimeException: Infinite loop creating new page due to column header overflow exception in cases when datasource has a lot of elements;
Change the table's subDataset dataSourceExpression to value below, that is relevant to your Java code:
<datasetRun subDataset="New Dataset 1" uuid="f5f39e4f-4349-4e5d-9736-03f84a7a7617">
<dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></dataSourceExpression>
</datasetRun>
I'm building a chart in iReports and when I compile in Eclipse I get the following error:
net.sf.jasperreports.engine.JRException: Errors were encountered when compiling report expressions class file:
1. net.sf.jasperreports.engine.JRBeanCollectionDataSource cannot be resolved to a type
value = new net.sf.jasperreports.engine.JRBeanCollectionDataSource(((java.lang.String)field_chartData46xAxis.getValue())); //$JR_EXPR_ID=11$
<---------------------------------------------------->
2. net.sf.jasperreports.engine.JRBeanCollectionDataSource cannot be resolved to a type
value = new net.sf.jasperreports.engine.JRBeanCollectionDataSource(((java.lang.String)field_chartData46xAxis.getOldValue())); //$JR_EXPR_ID=11$
<---------------------------------------------------->
3. net.sf.jasperreports.engine.JRBeanCollectionDataSource cannot be resolved to a type
value = new net.sf.jasperreports.engine.JRBeanCollectionDataSource(((java.lang.String)field_chartData46xAxis.getValue())); //$JR_EXPR_ID=11$
<---------------------------------------------------->3 errors
at net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:204)
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:240)
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:173)
at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:448)
at org.reportprotojava.protosheet.Program.main(Program.java:122)
I pass an ArrayList of ProtoReport (only one right now while I test) to the jasper compiler. The ProtoReport class contains a ChartData class which in turns has two ArrayList of type Double, one for the X-axis and one for the Y-axis.
The definitions of the ProtoReport, ChartData classes, and main program are as follows(slightly abridged):
ProtoReport Class:
package org.reportprotojava.protosheet;
import java.util.ArrayList;
public class ProtoReport {
private String outputFileName;
private String title;
private String logoLocation;
private String paragraphText;
private ArrayList<String> tableData;
private String picLocation;
private int[][] graphData; //TODO decide how to store chart data
private ChartData chartData;
private String path;
//default constructor
public ProtoReport() {
// Initialize object fields
outputFileName = "PrototypeReport";
title = "Prototype Report";
paragraphText = "Default text";
tableData = new ArrayList<String>();
chartData = new ChartData();
//set path to working directory
path = System.getProperty("user.dir");
//default to assumed report location
//(ie same folder as .jrxml and .jasper files)
logoLocation = path + "\\reports\\logo.jpg";
picLocation = path + "\\reports\\pic.jpg";
}
ChartData Class:
package org.reportprotojava.protosheet;
import java.util.ArrayList;
public class ChartData {
private ArrayList<Double> xAxis;
private ArrayList<Double> yAxis;
/**
* #param xAxis
* #param yAxis
*/
//default constructor
public ChartData(){
xAxis = new ArrayList<Double>();
yAxis = new ArrayList<Double>();
}
//constructor
public ChartData(ArrayList<Double> xAxis, ArrayList<Double> yAxis) {
super();
this.xAxis = xAxis;
this.yAxis = yAxis;
}
Main Program
public class Program {
/**
* #param args
*
*Program runs our ProtoReport class and its supporting classes
* In the end we will have generated a .pdf from the
* previously defined .jrxml file
*/
//Generate some random data for the chart
public static ArrayList<Double> randomData(int size) {
ArrayList<Double> arrayList = new ArrayList<Double>();
double randNumber;
for (int i = 0; i < size; i++) {
randNumber = Math.random();
arrayList.add(randNumber);
}
return arrayList;
}
public static void main(String[] args) {
ArrayList<ProtoReport> listOfReports = new ArrayList<ProtoReport>();
ProtoReport protoReport1 = new ProtoReport();
ProtoReport protoReport2 = new ProtoReport();
//Simple Fields and text
protoReport1.setTitle("Example<br/>Fact Sheet");
protoReport1.setLogoLocation(protoReport1.getPath() + "\\reports\\logo.gif");
ChartData chartData = new ChartData();
chartData.setYAxis(randomData(20));
for (Double i = (double) 0; i < chartData.getYAxis().size(); i++) {
chartData.getXAxis().add(i);
}
protoReport1.setChartData(chartData);
String jrxmlLocation = protoReport1.getPath()
+ "\\reports\\ReportPrototype.jrxml";
String outputFileName = protoReport1.getPath()
+ "\\reports\\generated\\" + protoReport1.getOutputFileName() + ".pdf";
listOfReports.add(protoReport1);
//and wrap the ArrayList in a JRBeanCollectionDataSource
JRBeanCollectionDataSource beanBurritoWrap = new JRBeanCollectionDataSource(listOfReports);
//build the jasper report
JasperReport jasperReport;
JasperPrint jasperPrint;
HashMap<String, Object> hashMap = new HashMap<>();
boolean reportCreated;
try {
jasperReport = JasperCompileManager.compileReport(jrxmlLocation);
jasperPrint = JasperFillManager.fillReport(jasperReport, hashMap, beanBurritoWrap);
JasperExportManager.exportReportToPdfFile(jasperPrint, outputFileName);
reportCreated=true;
}
catch (JRException e) {
e.printStackTrace();
reportCreated=false;
}
}
I've googled the problem and come up with this and this, and read the datasource section on jasper sourceforge but none of these have helped solve the problem, and I've made sure that I've used
new net.sf.jasperreports.engine.JRBeanCollectionDataSource($F{chartData.xAxis})
in my chart data source expression(and updated it when I change field names) and the fields are set to the List type in the iReport properties.
Here is my .jrxml
<?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="ReportPrototype.jrxml" pageWidth="595" pageHeight="842" columnWidth="495" leftMargin="57" rightMargin="43" topMargin="43" bottomMargin="43" uuid="10825c57-f953-4166-bf03-8ecabe8a8f47">
<property name="ireport.zoom" value="0.75"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="232"/>
<subDataset name="ChartData" uuid="fc9ec0af-3e1a-40a7-8eb4-9ad30a266dee">
<field name="chartData.xAxis" class="java.lang.String"/>
</subDataset>
<queryString language="SQL">
<![CDATA[]]>
</queryString>
<field name="title" class="java.lang.String"/>
<field name="logoLocation" class="java.lang.String"/>
<field name="picLocation" class="java.lang.String"/>
<field name="chartData.xAxis" class="java.lang.String"/>
<detail>
<band height="740" splitType="Stretch">
<textField isStretchWithOverflow="true" pattern="">
<reportElement uuid="519c6bb5-72f9-4c25-8e91-47865ae0c9df" mode="Opaque" x="39" y="75" width="378" height="45" forecolor="#000099"/>
<textElement textAlignment="Center" verticalAlignment="Middle" markup="html">
<font size="26"/>
</textElement>
<textFieldExpression><![CDATA[$F{title}]]></textFieldExpression>
</textField>
<image onErrorType="Icon">
<reportElement uuid="3759a707-32a4-49ef-a9c6-b0ad7136f738" x="216" y="264" width="279" height="246"/>
<imageExpression><![CDATA[$F{picLocation}]]></imageExpression>
</image>
<image onErrorType="Icon">
<reportElement uuid="f989f871-32ea-4f13-ae3f-3f487cde76dd" x="295" y="0" width="200" height="42"/>
<imageExpression><![CDATA[$F{logoLocation}]]></imageExpression>
</image>
<xyLineChart>
<chart>
<reportElement uuid="ae87fc13-b92e-4a2a-b218-d395343f6028" x="0" y="537" width="495" height="203"/>
<chartTitle/>
<chartSubtitle/>
<chartLegend/>
</chart>
<xyDataset>
<dataset>
<datasetRun subDataset="ChartData" uuid="de7fb84d-17ea-4e5e-82bf-2015e72e4982">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JRBeanCollectionDataSource($F{chartData.xAxis})]]></dataSourceExpression>
</datasetRun>
</dataset>
</xyDataset>
<linePlot>
<plot/>
</linePlot>
</xyLineChart>
</band>
</detail>
<pageFooter>
<band height="16">
<break>
<reportElement uuid="0d30dea4-a6af-4e41-b7be-c288f3188dbf" x="0" y="11" width="100" height="1"/>
</break>
</band>
</pageFooter>
In iReports I've tried:
-Creating and naming fields ProtoReport.ChartData.xAxis and ProtoReport.ChartData.yAxis under Fields and the fields under the ChartData source I added
-Renaming the fields to ChartData.xAxis and ChartData.yAxis
-Renaming the fields to chartData.xAxis and chartData.yAxis
-Just using the fields under Field
-Just using the fields under ChartData - Fields
All give me an error. Any ideas what I'm doing wrong?
Additional questions:
-As it stands my chart will likely only produce the xAxis data points. How can I use the contents of one ArrayList for the X-axis and the other for the Y-Axis? ie my xAxis and yAxis fields in ChartData object.
-The randomData() method I declared before main would not run until I declared it static, why is that?
Edit
To state my question more clearly: How do I name my fields, setup my datasources, and configure my datasets in order to solve this problem?
I am following the tutorial listed in the comments (sorry for the non-hyper link; as a new user I've used all my hyperlinks already), and making changes to it for my needs, but his data structure is more simple than mine and I'd like to learn how to deal with more complex objects and datasets in jasper reports.
In the .jrxml the data source for the chart is defined as:
<![CDATA[new net.sf.jasperreports.engine.JRBeanCollectionDataSource($F{chartData.xAxis})]]>
This come from the iReports 4.7.0 autofill when you select Use datasource expression under Connection/Datasource exp in the details pane, the default expression from iReports is:
new net.sf.jasperreports.engine.JREmptyDataSource(1)
But this expression is wrong because .data is missing. It should read:
new net.sf.jasperreports.engine.data.JREmptyDataSource(1)
and then I changed the JREmptyDataSource(1) to JRBeanCollectionDataSource($F{chartData}) of course
This fixes the compile time error and then I had to reorganize and redefine my Lists and POJO's so that I could easily access the data point pairs in my List of ChartData objects. Essentially this meant that instead of a single ChartData object with two lists of doubles (one for X-Axis and one for Y-Axis), I now have a list of ChartData objects, each with just one XY point. This seems to work well for now.