Collections 不同键的和值(不分组) 背景
考虑以下几点: 方法2 创建Collections 不同键的和值(不分组) 背景,collections,sum,jasper-reports,Collections,Sum,Jasper Reports,考虑以下几点: 方法2 创建MappedIncrementerFactory和MappedIncrementer,类似于JRDistinctCountIncrementerFactory和JRDistinctCountIncrementer 方法3 预先计算总计,并使用数据对象模型将其传入。例如: public class DataSetItem { public String getName() { ... } public String getMode() { ... }
MappedIncrementerFactory
和MappedIncrementer
,类似于JRDistinctCountIncrementerFactory
和JRDistinctCountIncrementer
方法3
预先计算总计,并使用数据对象模型将其传入。例如:
public class DataSetItem {
public String getName() { ... }
public String getMode() { ... }
public Integer getTally() { ... }
}
public class DataSet {
public List<DataSetItem> getDataSetItemList() { ... }
public Map<String, Integer> getDataSetTotals() { ... }
}
public class DataSetFactory {
/** Returns a single instance that has the list of items and totals. */
public List<DataSet> createDataSetItemCollection() { ... }
}
公共类数据源项{
公共字符串getName(){…}
公共字符串getMode(){…}
公共整数gettaly(){…}
}
公共类数据集{
公共列表getDataSetItemList(){…}
公共映射getDataSetTotals(){…}
}
公共类数据集工厂{
/**返回包含项目和总计列表的单个实例*/
公共列表createDataSetItemCollection(){…}
}
方法4
使用Scriptlet并返回值的JRDataSource
问题:
如何创建包含键/值对的集合类型变量(映射),其中每个值都是与键名称匹配的报告行的总和?这将是方法4:使用
涂鸦课
scriplet将求和并存储数据,以便稍后(在所有细节之后)返回数据源。注意:Nullpointer
或数据源的其他问题不被考虑
public class Scriplet extends JRDefaultScriptlet {
private Map<String, TxSubTotal> subTotals; //Use map for quick access
private int lastRecNr = 0; //Jasper has a bad habit of calling twice
public Scriplet(){
super();
subTotals = new HashMap<>();
}
@Override
public void afterDetailEval() throws JRScriptletException {
int recNr = ((Integer)this.getVariableValue("REPORT_COUNT"));
if (lastRecNr==recNr){ //Check we only count once per record
return;
}
lastRecNr=recNr;
String key = (String)this.getFieldValue("Mode");
int value = ((Integer)this.getFieldValue("Tally")).intValue();
TxSubTotal tst = subTotals.get(key);
if (tst == null){
tst = new TxSubTotal(key);
subTotals.put(key, tst);
}
tst.addTotal(value);
super.afterDetailEval();
}
//This is our datasource
public JRRewindableDataSource getSubTotalDataSource(){
List<TxSubTotal> txList = new ArrayList<>();
//add some sorting to show the power of scriplet
txList.addAll(subTotals.values());
Collections.sort(txList);
return new JRBeanCollectionDataSource(txList);
}
}
jrxml
将scriptlet设置为报告
scriptletClass="Scriplet"
这个jrxml使用jr:table
组件来显示数据,但也可以使用子报表。关键是在摘要栏中使用它,或者在表/子报表组件上使用evaluationTime=“report”
。数据源表达式将是
<dataSourceExpression><![CDATA[$P{REPORT_SCRIPTLET}.getSubTotalDataSource()]]></dataSourceExpression>
完整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="Jarvis" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" scriptletClass="Scriplet" uuid="d626fd77-14da-4974-8b4f-6368e913ac91">
<style name="table">
<box>
<pen lineWidth="0.25" lineColor="#000000"/>
</box>
</style>
<style name="table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<subDataset name="subTotals" uuid="486941af-2c8f-4ebb-8b8a-7a1dfe2ac0ad">
<field name="mode" class="java.lang.String"/>
<field name="total" class="java.lang.Integer"/>
</subDataset>
<queryString>
<![CDATA[]]>
</queryString>
<field name="Name" class="java.lang.String"/>
<field name="Mode" class="java.lang.String"/>
<field name="Tally" class="java.lang.Integer"/>
<background>
<band splitType="Stretch"/>
</background>
<columnHeader>
<band height="20" splitType="Stretch">
<staticText>
<reportElement mode="Opaque" x="0" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="30cd16d8-6765-42f9-b5f9-22bc0625adca"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="100" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="88418f9a-5d2b-487e-b04d-e11bc57726d7"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Mode]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="200" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="dd2495bb-3a3d-4b0e-b986-055bf55cf19b"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<text><![CDATA[Tally]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20" uuid="53931171-df80-43e7-9b9d-5d77ce4223dc"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Name}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20" uuid="f809c675-c68b-4ad0-b662-23ba6e9dd70c"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Mode}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="200" y="0" width="100" height="20" uuid="0852ff01-aa61-4a7f-9c11-a481b78b56fd"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Tally}]]></textFieldExpression>
</textField>
</band>
</detail>
<summary>
<band height="75" splitType="Stretch">
<componentElement>
<reportElement key="table" style="table" x="120" y="25" width="180" height="50" uuid="5158e7c3-d87d-4877-a3ab-d6a6f9a57c5a"/>
<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="subTotals" uuid="9b73e50e-4bdf-41c2-8d40-4d215fe6b6e9">
<dataSourceExpression><![CDATA[$P{REPORT_SCRIPTLET}.getSubTotalDataSource()]]></dataSourceExpression>
</datasetRun>
<jr:column width="90" uuid="cbb85338-16b3-487d-8045-6dd94c661fc0">
<jr:detailCell style="table_TD" height="30" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="30" uuid="5c07b5af-9e28-4a14-a70a-3789bfc88087"/>
<box leftPadding="2" rightPadding="2"/>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{mode}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="90" uuid="d69567f0-ec7c-4b83-bc22-5aae1cab7879">
<jr:detailCell style="table_TD" height="30" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="30" uuid="2a3a2055-f9c0-46e3-b816-b6ee1c989f9c"/>
<box leftPadding="2" rightPadding="2"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{total}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
<staticText>
<reportElement x="120" y="5" width="180" height="20" uuid="9ef22e85-34ce-47c9-afad-2813a8a0b863"/>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Tx SubTotals]]></text>
</staticText>
</band>
</summary>
</jasperReport>
从包含相关数据的cvs文件生成pdf导出的主要方法
publicstaticvoidmain(字符串[]args)抛出JRException、FileNotFoundException{
JasperReport report=jaspecompilemanager.compileReport(“myReport.jrxml”);
JRCsvDataSource datasource=新的JRCsvDataSource(新文件(“data/datasource.csv”);
datasource.setFieldDelimiter(“;”);
datasource.setUseFirstRowaHeader(true);
setLocale(Locale.US);
JasperPrint JasperPrint=JasperFillManager.fillReport(报告,新HashMap(),数据源);
JRPdfExporter exporter=新的JRPdfExporter();
exporter.setExporterInput(新的SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(新的SimpleOutputStreamExporterOutput(“pdf/example.pdf”);
SimplePDExporterConfiguration配置=新的SimplePDExporterConfiguration();
exporter.setConfiguration(配置);
出口商。出口报告();
}
结果
一般解决方案如下。键和值列元组的名称在子报表中设置为参数。主报告包含scriptlet、子报告和总计摘要页面。这在有许多几乎相同的子报表的情况下非常有用,但只有一些子报表需要基于列元组的总计 每个具有总元组的子报表必须分别为关键参数和值参数定义一个值:
SCRIPTLET_key_COLUMN_NAME
和SCRIPTLET_value_COLUMN_NAME
。如果未在子报表中设置键参数,则isSubreport()
将返回false,并且不会执行求和
程序段
主报表运行以下scriptlet,通过将scriptlet类设置为com.company.jasper.TupleSumScriptlet
来配置它
package com.company.jasper;
import java.util.*;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
public class TupleSumScriplet extends JRDefaultScriptlet {
private final static String REPORT_KEY_COLUMN_NAME
= "SCRIPTLET_KEY_COLUMN_NAME";
private final static String REPORT_VALUE_COLUMN_NAME
= "SCRIPTLET_VALUE_COLUMN_NAME";
private final Map<String, Integer> sums = new HashMap<>();
public TupleSumScriplet() { }
@Override
public void afterDetailEval() throws JRScriptletException {
if (isSubreport()) {
final String keyColumnName = getKeyColumnName();
final String key = (String) getFieldValue(keyColumnName);
final String valueColumnName = getValueColumnName();
final int value = (Integer) getFieldValue(valueColumnName);
final Map<String, Integer> totals = getSums();
final int sum = totals.containsKey(key) ? totals.get(key) : 0;
totals.put(key, sum + value);
}
}
public JRDataSource getDataSource() {
return new JRBeanCollectionDataSource(sort(getSums()));
}
public Map<String, Integer> getSums() {
return this.sums;
}
private String getKeyColumnName() throws JRScriptletException {
return (String) getParameterValue(REPORT_KEY_COLUMN_NAME);
}
protected String getValueColumnName() throws JRScriptletException {
return (String) getParameterValue(REPORT_VALUE_COLUMN_NAME);
}
private boolean isSubreport() {
boolean result;
try {
result = true;
final String unused = getKeyColumnName();
} catch (JRScriptletException e) {
result = false;
}
return result;
}
public static
<K extends Comparable<? super K>, V> Collection<Map.Entry<K, V>>
sort(Map<K, V> map) {
final List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o1.getKey()).compareTo(o2.getKey());
}
});
return list;
}
}
总计子报告的相关JRXML如下所示:
scriptletClass="Scriplet"
<dataSourceExpression><![CDATA[$P{REPORT_SCRIPTLET}.getSubTotalDataSource()]]></dataSourceExpression>
<?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="Jarvis" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" scriptletClass="Scriplet" uuid="d626fd77-14da-4974-8b4f-6368e913ac91">
<style name="table">
<box>
<pen lineWidth="0.25" lineColor="#000000"/>
</box>
</style>
<style name="table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<subDataset name="subTotals" uuid="486941af-2c8f-4ebb-8b8a-7a1dfe2ac0ad">
<field name="mode" class="java.lang.String"/>
<field name="total" class="java.lang.Integer"/>
</subDataset>
<queryString>
<![CDATA[]]>
</queryString>
<field name="Name" class="java.lang.String"/>
<field name="Mode" class="java.lang.String"/>
<field name="Tally" class="java.lang.Integer"/>
<background>
<band splitType="Stretch"/>
</background>
<columnHeader>
<band height="20" splitType="Stretch">
<staticText>
<reportElement mode="Opaque" x="0" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="30cd16d8-6765-42f9-b5f9-22bc0625adca"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="100" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="88418f9a-5d2b-487e-b04d-e11bc57726d7"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Mode]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="200" y="0" width="100" height="20" forecolor="#000000" backcolor="#CCCCCC" uuid="dd2495bb-3a3d-4b0e-b986-055bf55cf19b"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<text><![CDATA[Tally]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20" uuid="53931171-df80-43e7-9b9d-5d77ce4223dc"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Name}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20" uuid="f809c675-c68b-4ad0-b662-23ba6e9dd70c"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Mode}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="200" y="0" width="100" height="20" uuid="0852ff01-aa61-4a7f-9c11-a481b78b56fd"/>
<box leftPadding="2" rightPadding="2">
<pen lineWidth="0.25"/>
<topPen lineWidth="0.25"/>
<leftPen lineWidth="0.25"/>
<bottomPen lineWidth="0.25"/>
<rightPen lineWidth="0.25"/>
</box>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{Tally}]]></textFieldExpression>
</textField>
</band>
</detail>
<summary>
<band height="75" splitType="Stretch">
<componentElement>
<reportElement key="table" style="table" x="120" y="25" width="180" height="50" uuid="5158e7c3-d87d-4877-a3ab-d6a6f9a57c5a"/>
<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="subTotals" uuid="9b73e50e-4bdf-41c2-8d40-4d215fe6b6e9">
<dataSourceExpression><![CDATA[$P{REPORT_SCRIPTLET}.getSubTotalDataSource()]]></dataSourceExpression>
</datasetRun>
<jr:column width="90" uuid="cbb85338-16b3-487d-8045-6dd94c661fc0">
<jr:detailCell style="table_TD" height="30" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="30" uuid="5c07b5af-9e28-4a14-a70a-3789bfc88087"/>
<box leftPadding="2" rightPadding="2"/>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{mode}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="90" uuid="d69567f0-ec7c-4b83-bc22-5aae1cab7879">
<jr:detailCell style="table_TD" height="30" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="30" uuid="2a3a2055-f9c0-46e3-b816-b6ee1c989f9c"/>
<box leftPadding="2" rightPadding="2"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{total}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
<staticText>
<reportElement x="120" y="5" width="180" height="20" uuid="9ef22e85-34ce-47c9-afad-2813a8a0b863"/>
<textElement verticalAlignment="Middle"/>
<text><![CDATA[Tx SubTotals]]></text>
</staticText>
</band>
</summary>
</jasperReport>
public static void main(String[] args) throws JRException, FileNotFoundException {
JasperReport report = JasperCompileManager.compileReport("myReport.jrxml");
JRCsvDataSource datasource = new JRCsvDataSource(new File("data/datasource.csv"));
datasource.setFieldDelimiter(';');
datasource.setUseFirstRowAsHeader(true);
datasource.setLocale(Locale.US);
JasperPrint jasperPrint = JasperFillManager.fillReport(report, new HashMap<String, Object>(), datasource);
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput("pdf/example.pdf"));
SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
exporter.setConfiguration(configuration);
exporter.exportReport();
}
package com.company.jasper;
import java.util.*;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
public class TupleSumScriplet extends JRDefaultScriptlet {
private final static String REPORT_KEY_COLUMN_NAME
= "SCRIPTLET_KEY_COLUMN_NAME";
private final static String REPORT_VALUE_COLUMN_NAME
= "SCRIPTLET_VALUE_COLUMN_NAME";
private final Map<String, Integer> sums = new HashMap<>();
public TupleSumScriplet() { }
@Override
public void afterDetailEval() throws JRScriptletException {
if (isSubreport()) {
final String keyColumnName = getKeyColumnName();
final String key = (String) getFieldValue(keyColumnName);
final String valueColumnName = getValueColumnName();
final int value = (Integer) getFieldValue(valueColumnName);
final Map<String, Integer> totals = getSums();
final int sum = totals.containsKey(key) ? totals.get(key) : 0;
totals.put(key, sum + value);
}
}
public JRDataSource getDataSource() {
return new JRBeanCollectionDataSource(sort(getSums()));
}
public Map<String, Integer> getSums() {
return this.sums;
}
private String getKeyColumnName() throws JRScriptletException {
return (String) getParameterValue(REPORT_KEY_COLUMN_NAME);
}
protected String getValueColumnName() throws JRScriptletException {
return (String) getParameterValue(REPORT_VALUE_COLUMN_NAME);
}
private boolean isSubreport() {
boolean result;
try {
result = true;
final String unused = getKeyColumnName();
} catch (JRScriptletException e) {
result = false;
}
return result;
}
public static
<K extends Comparable<? super K>, V> Collection<Map.Entry<K, V>>
sort(Map<K, V> map) {
final List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o1.getKey()).compareTo(o2.getKey());
}
});
return list;
}
}
$P{REPORT_SCRIPTLET}.getDataSource()