Using CustomExpression in a DynamicJasper Chart

I have a project using DynamicJasper to create reports. While this works, but when I wanted to add a chart to a previously functional report, I ran into problems.

I keep getting the following:

net.sf.jasperreports.engine.design.JRValidationException: report design is invalid: 1. Field not found: customExpression_for_Ganancia at net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign (JRAbstractCompiler.java:258) at net.sf.jasper .engine.design.JRAbstractCompiler.compileReport (JRAbstractCompiler.java:140) at net.sf.jasperreports.engine.JasperCompileManager.compileReport (JasperCompileManager.java:215) on ar.com.fdvs .dj.core.DynamicJperHperperperJperHperper .java: 519) on ar.com.fdvs .dj.core.DynamicJasperHelper.generateJasperPrint (DynamicJasperHelper.java:279) on ar.com.fdvs .dj.core.DynamicJasperHelper.generateJasperPrint (DynamicJasperHelper.java:232)

Ganancia is the only column in the chart that is CustomExpression. If I do not add this column to the series in the chart, the chart will display correctly. It seems that the diagram does not work very well with expressions ...

Excerpt from my code:

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(); } }; 

As I said, the report is displayed correctly without a chart; with a chart, it fails only if the expression column is included as a series.

Any ideas are welcome!

+4
source share
3 answers

Just pushed change for DJ 4.0.1 in commit 05243a3

DJ 3.X will also be pushing for some time today.

+1
source

I solved the same problem by following these steps:

  • Set the "fieldDescription" of your column.
  • Rewrite the method "protected Map registerChartVariable (ar.com.fdvs .dj.domain.chart.DJChart chart)" of the AbstractLayoutManager class:

expression JRDesignExpression = new expression JRDesignExpression ();

 String property = ((PropertyColumn) col).getFieldDescription(); 

// ((PropertyColumn) col) .getColumnProperty (). getProperty ();

 expression.setText("$F{" + property + "}"); expression.setValueClass(clazz); 

3. As you already found out, you will have to create your own LayoutManager for this task. 4. This may not be the best solution, it is just an example of how to fill in the gap DynamicJasper.

+1
source

I ran into the same problem, but I had a slightly different solution. Column class classes exist, but only the PropertyColumn class is supported in AbstractLayoutManager diagrams. I learned that when using CustomExpression base Column class that is used is ExpressionColumn . So, I modified the "protected Map registerChartVariable() method in ar.com.fdvs.dj.core.layout.AbstractLayoutManager to support ExpressionColumn .

In this method, I changed the following 3 lines of code:

 JRDesignExpression expression = new JRDesignExpression(); expression.setText("$F{" + ((PropertyColumn) col).getColumnProperty().getProperty() + "}"); expression.setValueClass(clazz); 

To the next:

 if (col instanceof ExpressionColumn) { ExpressionColumn expCol = (ExpressionColumn) col; expression.setText(expCol.getTextForExpression()); expression.setValueClassName(expCol.getExpression().getClassName()); } else { expression.setText("$F{" + ((PropertyColumn) col).getColumnProperty().getProperty() + "}"); expression.setValueClass(clazz); } 

This resolved the issue for me and I no longer receive the message Field not found .

0
source

Source: https://habr.com/ru/post/1348148/


All Articles