简体   繁体   English

在DynamicJasper图表中使用CustomExpression

[英]Using a CustomExpression in a DynamicJasper chart

I have a project using DynamicJasper to create reports. 我有一个使用DynamicJasper创建报告的项目。 It works fine so far, but when I wanted to add a chart to a previously functional report I run into issues. 到目前为止,它仍然可以正常工作,但是当我想向以前的功能报告中添加图表时,遇到了问题。

I keep getting this: 我不断得到这个:

net.sf.jasperreports.engine.design.JRValidationException: Report design not valid : 1. Field not found : customExpression_for_Ganancia at net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign(JRAbstractCompiler.java:258) at net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:140) at 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) net.sf.jasperreports.engine.design.JRValidationException:报告设计无效:1.找不到字段:net.sf处net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign(JRAbstractCompiler.java:258)处的customExpression_for_Ganancia。 net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:215)上的jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:140)at ar.com.fdvs.dj.core.DynamicJasperHelper(generate) ar.com.fdvs.dj.core.DynamicJasperHelper.generateJasperPrint(DynamicJasperHelper.java:279)上的DynamicJasperHelper.java:519)ar.com.fdvs.dj.core.DynamicJasperHelper.generateJasperPrint(DynamicJasperHelper.java:232)

Ganancia being the only column in the chart that is a CustomExpression. Ganancia是图表中唯一的CustomExpression列。 If I don't add this column as a series to the chart, the chart renders properly. 如果我不将此列作为系列添加到图表中,则图表将正确呈现。 It seems the chart doesn't play well with expressions... 该图表似乎不适用于表达式...

A snippet 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 shown properly without the chart, with the chart, it fails only if the expression column is included as a series. 就像我说过的那样,该报告在没有图表的情况下正确显示,只有在将表达式列作为系列包含时,该报告才会失败。

Any ideas are welcomed! 任何想法都欢迎!

Just pushed the change for DJ 4.0.1 in commit 05243a3 刚刚在提交05243a3中推送了DJ 4.0.1的更改

Sometime today will also push for DJ 3.X 今天的某个时候还将推动DJ 3.X

I've solved this very same problem doing the following: 我已经通过以下方法解决了这个非常相同的问题:

  1. Set the "fieldDescription" of your column. 设置列的“ fieldDescription”。
  2. Re-write the Method "protected Map registerChartVariable(ar.com.fdvs.dj.domain.chart.DJChart chart)" of class AbstractLayoutManager": 重新编写类AbstractLayoutManager的“受保护的映射registerChartVariable(ar.com.fdvs.dj.domain.chart.DJChart图表)”方法:

JRDesignExpression expression = new JRDesignExpression(); JRDesignExpression表达式=新的JRDesignExpression();

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

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

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

3 . 3。 As you have already figured out, you'll have to create your own LayoutManager for this task. 正如您已经知道的那样,您必须为此任务创建自己的LayoutManager。 4 . 4。 This may not be the best solution, it is just an example how to fill the gap of DynamicJasper. 这可能不是最佳解决方案,它只是如何填补DynamicJasper空白的一个示例。

I ran into the same problem, but I had a slightly different solution. 我遇到了同样的问题,但解决方案略有不同。 There are different types of Column classes, but only the PropertyColumn class is supported in the AbstractLayoutManager for charts. Column类的类型不同,但是AbstractLayoutManager仅支持针对图表的PropertyColumn类。 I found out that when you use a CustomExpression , the underlying Column class that is used is an ExpressionColumn . 我发现,当您使用CustomExpression时,使用的基础Column类是ExpressionColumn So, I modified the "protected Map registerChartVariable() method in the ar.com.fdvs.dj.core.layout.AbstractLayoutManager to support ExpressionColumn . 因此,我修改了ar.com.fdvs.dj.core.layout.AbstractLayoutManager的“受保护的map registerChartVariable()方法”以支持ExpressionColumn

I changed the following 3 lines of code in that method: 我在该方法中更改了以下3行代码:

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

To the following: 要以下内容:

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 problem for me and I no longer get the " Field not found " message. 这为我解决了问题,并且我不再收到“ 找不到字段 ”消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM