У меня есть проект, использующий DynamicJasper для создания отчетов. Пока все работает нормально, но когда я захотел добавить диаграмму в ранее работающий отчет, у меня возникли проблемы.
Я продолжаю получать это:
net.sf.jasperreports.engine.design.JRValidationException: дизайн отчета недействителен:
1. Поле не найдено: customExpression_for_Ganancia
в net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign (JRAbstractCompiler.java:258)
в net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport (JRAbstractCompiler.java:140)
в net.sf.jasperreports.engine.JasperCompileManager.compileReport (JasperCompileManager.java:215)
at ar.com.fdvs.dj.core.DynamicJasperHelper.generateJasperReport (DynamicJasperHelper.java:519)
at ar.com.fdvs.dj.core.DynamicJasperHelper.generateJasperPrint (DynamicJasperHelper.java:279)
at ar.com.fdvs.dj.core.DynamicJasperHelper.generateJasperPrint (DynamicJasperHelper.java:232)
Ganancia является единственным столбцом на диаграмме, который является CustomExpression. Если я не добавлю этот столбец в виде ряда на график, он будет отображаться правильно. Кажется, диаграмма плохо сочетается с выражениями ...
Фрагмент из моего кода:
private DynamicReport buildSalesReport() throws ColumnBuilderException, ClassNotFoundException, ChartBuilderException {
DynamicReportBuilder drb = new DynamicReportBuilder();
drb.setReportName("Reporte de Ventas")
.setTitle("Reporte de ventas")
.setSubtitle("Este reporte fue generado el " + new Date())
.setPrintColumnNames(false)
.setIgnorePagination(true)
.setMargins(10, 10, 10, 10)
.setUseFullPageWidth(true);
Style groupOneStyle = new Style();
groupOneStyle.setFont(Font.ARIAL_BIG);
groupOneStyle.setHorizontalAlign(HorizontalAlign.LEFT);
groupOneStyle.setVerticalAlign(VerticalAlign.MIDDLE);
AbstractColumn columnDisplayName = ColumnBuilder.getNew()
.setColumnProperty("bookingType.displayName", String.class.getName())
.setTitle("Tipo").setWidth(new Integer(40))
.setStyle(groupOneStyle)
.build();
AbstractColumn columnDestiny = ColumnBuilder.getNew()
.setColumnProperty("bookedObject.destiny", String.class.getName())
.setTitle("Destino").setWidth(new Integer(40))
.build();
Style priceStyle = new Style();
priceStyle.setHorizontalAlign(HorizontalAlign.RIGHT);
AbstractColumn columnCurrency = ColumnBuilder.getNew()
.setColumnProperty("bookedObject.currency.displayName", String.class.getName())
.setTitle("Cotizacion").setWidth(new Integer(5))
.setShowText(false)
.build();
Style footerStyle = new Style();
footerStyle.setFont(Font.ARIAL_MEDIUM);
footerStyle.setBorderTop(Border.THIN);
footerStyle.setHorizontalAlign(HorizontalAlign.RIGHT);
footerStyle.setVerticalAlign(VerticalAlign.MIDDLE);
AbstractColumn columnPrice = ColumnBuilder.getNew()
.setColumnProperty("bookedObject.price", Double.class.getName())
.setStyle(priceStyle)
.setPattern("$ 0.00")
.setTitle("Precio").setWidth(new Integer(25))
.build();
AbstractColumn columnCount = ColumnBuilder.getNew()
.setColumnProperty("count", Integer.class.getName())
.setStyle(priceStyle)
.setTitle("Cantidad").setWidth(new Integer(25))
.build();
columnCount.setName("Cantidad");
AbstractColumn columnProfit = ColumnBuilder.getNew()
.setCustomExpression(this.getProfitExpression())
.setStyle(priceStyle)
.setTitle("Ganancia").setWidth(new Integer(20))
.setPattern("$ 0.00")
.build();
columnProfit.setName("Ganancia");
GroupBuilder groupBookingTypeBuilder = new GroupBuilder();
DJGroup groupBookingType =
groupBookingTypeBuilder.setCriteriaColumn((PropertyColumn) columnDisplayName)
.setGroupLayout(GroupLayout.VALUE_IN_HEADER_WITH_HEADERS_AND_COLUMN_NAME)
.build();
GroupBuilder groupCurrencyBuilder = new GroupBuilder();
DJGroup groupCurrency =
groupCurrencyBuilder.setCriteriaColumn((PropertyColumn) columnCurrency)
.addFooterVariable(columnCount,DJCalculation.SUM,footerStyle)
.addFooterVariable(columnProfit,DJCalculation.SUM,footerStyle)
.setGroupLayout(GroupLayout.VALUE_IN_HEADER)
.build();
drb.addColumn(columnDisplayName)
.addColumn(columnCurrency)
.addColumn(columnDestiny)
.addColumn(columnCount)
.addColumn(columnPrice)
.addColumn(columnProfit)
.addGroup(groupBookingType)
.addGroup(groupCurrency)
.setPrintBackgroundOnOddRows(true);
DJAxisFormat categoryAxisFormat = new DJAxisFormat("Destino");
categoryAxisFormat.setLabelFont(Font.ARIAL_SMALL);
categoryAxisFormat.setLabelColor(Color.DARK_GRAY);
categoryAxisFormat.setTickLabelFont(Font.ARIAL_SMALL);
categoryAxisFormat.setTickLabelColor(Color.DARK_GRAY);
categoryAxisFormat.setTickLabelMask("");
categoryAxisFormat.setLineColor(Color.DARK_GRAY);
DJAxisFormat valueAxisFormat = new DJAxisFormat("Ventas / Ingresos");
valueAxisFormat.setLabelFont(Font.ARIAL_SMALL);
valueAxisFormat.setLabelColor(Color.DARK_GRAY);
valueAxisFormat.setTickLabelFont(Font.ARIAL_SMALL);
valueAxisFormat.setTickLabelColor(Color.DARK_GRAY);
valueAxisFormat.setTickLabelMask("#,##0");
valueAxisFormat.setLineColor(Color.DARK_GRAY);
DJChart djChart = new DJBarChartBuilder()
//chart
.setX(20)
.setY(10)
.setWidth(500)
.setHeight(250)
.setCentered(false)
.setBackColor(Color.LIGHT_GRAY)
.setShowLegend(true)
.setPosition(DJChartOptions.POSITION_FOOTER)
.setTitle(new StringExpression() {
@Override
public Object evaluate(Map fields, Map variables, Map parameters) {
return variables.get("bookingType.displayName");
}
})
.setTitleColor(Color.DARK_GRAY)
.setTitleFont(Font.ARIAL_BIG_BOLD)
.setSubtitle("subtitle")
.setSubtitleColor(Color.DARK_GRAY)
.setSubtitleFont(Font.COURIER_NEW_BIG_BOLD)
.setLegendColor(Color.DARK_GRAY)
.setLegendFont(Font.COURIER_NEW_MEDIUM_BOLD)
.setLegendBackgroundColor(Color.WHITE)
.setLegendPosition(DJChartOptions.EDGE_BOTTOM)
.setTitlePosition(DJChartOptions.EDGE_TOP)
.setLineStyle(DJChartOptions.LINE_STYLE_DOTTED)
.setLineWidth(1)
.setLineColor(Color.DARK_GRAY)
.setPadding(5)
//dataset
.setCategory((PropertyColumn) columnDestiny)
.addSerie(columnCount, "Cantidad")
.addSerie(columnProfit, "Ganancia") // IF I COMMENT THIS LINE THE CHART IS RENDERED
//plot
.setCategoryAxisFormat(categoryAxisFormat)
.setValueAxisFormat(valueAxisFormat)
.build();
drb.addChart(djChart);
HashMap vars = new HashMap();
vars.put(columnCount, new JRDesignVariable());
vars.put(columnProfit, new JRDesignVariable());
JRDesignGroup group = new JRDesignGroup();
djChart.transform(new DynamicJasperDesign(), "", group, group, vars, 0);
DynamicReport dr = drb.build();
return dr;
}
public JasperPrint getJasperPrint(String status, String userOwner,
String hourFrom, String hourTo, String dateFrom, String dateTo)
throws ColumnBuilderException, ClassNotFoundException, JRException, ChartBuilderException {
DynamicReport dr = this.buildSalesReport();
JRDataSource ds = new JRBeanCollectionDataSource(
this.bookService.getReportBooks(status, userOwner, hourFrom, hourTo, dateFrom, dateTo));
return DynamicJasperHelper.generateJasperPrint(dr , new ClassicLayoutManager(), ds);
}
/**
*
* @return
*/
@SuppressWarnings("serial")
private CustomExpression getProfitExpression() {
return new CustomExpression() {
@SuppressWarnings("rawtypes")
@Override
public Object evaluate(Map fields, Map variables, Map parameters) {
Double amount = (Integer)fields.get("count") * (Double)fields.get("bookedObject.price");
return amount;
}
@Override
public String getClassName() {
return Double.class.getName();
}
};
Как я уже сказал, отчет отображается правильно без диаграммы, а с диаграммой он завершается ошибкой только в том случае, если столбец выражения включен в виде серии.
Любые идеи приветствуются!