Hot questions for Using JasperReports in dynamic reports

Top Java Programmings / JasperReports / dynamic reports

Question:

I am using DynamicReports 4.1.1. since I depend on Java 1.6. The problem is, that all my reports are empty no matter which export format is being used. The pdfs have about 1600 Bytes, so there is no problem with writing as such. But no content. I have read that this can happen if the datasource ist empty, but this is not the case here. Has someone an idea?

 private void build() {
    try {
        JRDataSource c = new JRBeanCollectionDataSource(createDataSource());
        report()
                .setTemplate(Templates.reportTemplate)
                .columns(
                col.column("Item", "item", type.stringType()),
                col.column("Quantity", "quantity", type.integerType()),
                col.column("Unit price", "unitPrice", type.bigDecimalType()))
                .title(Templates.createTitleComponent("CollectionDatasource"))
                .detailFooter(cmp.line())
                .pageFooter(Templates.footerComponent)
                .noData(Templates.createTitleComponent("NoData"), cmp.text("There is no data"))
                .setDataSource(c);
        report().toPdf(new FileOutputStream("report4.pdf"));
    } catch (DRException e) {
        e.printStackTrace();
    }
}

private List<Data> createDataSource() {
    List<Data> data = new ArrayList<Data>();
    data.add(new Data("DVD", 5, new BigDecimal(30)));
    data.add(new Data("Book", 8, new BigDecimal(11)));
    data.add(new Data("PDA", 2, new BigDecimal(15)));
    return data;
}

private class Data {

    private String item;
    private Integer quantity;
    private BigDecimal unitPrice;

    public Data(String item, Integer quantity, BigDecimal unitPrice) {
        this.item = item;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public BigDecimal getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(BigDecimal unitPrice) {
        this.unitPrice = unitPrice;
    }

    @Override
    public String toString() {
        return "Data{" + "item=" + item + ", quantity=" + quantity + ", unitPrice=" + unitPrice + '}';
    }
  }

Answer:

What is wrong?

You made a minor mistake (looks like copy&paste issue) - you are generating code from not properly initialized JasperReportBuilder object.

You created two instances of JasperReportBuilder class:

report()
        .setTemplate(Templates.reportTemplate)
        .columns(
           col.column("Item", "item", type.stringType()),
           col.column("Quantity", "quantity", type.integerType()),
           col.column("Unit price", "unitPrice", type.bigDecimalType()))
        .title(Templates.createTitleComponent("CollectionDatasource"))
        .detailFooter(cmp.line())
        .pageFooter(Templates.footerComponent)
        .noData(Templates.createTitleComponent("NoData"), cmp.text("There is no data"))
        .setDataSource(c); // here is a first instance. It is initialized via builde. You should use instance for any actions
report().toPdf(new FileOutputStream("report4.pdf")); // the second instance. Just "blank" object, you are missed initializing via builder

The valid code in your case will be:

report()
        .setTemplate(Templates.reportTemplate)
        .columns(
           col.column("Item", "item", type.stringType()),
           col.column("Quantity", "quantity", type.integerType()),
           col.column("Unit price", "unitPrice", type.bigDecimalType()))
        .title(Templates.createTitleComponent("CollectionDatasource"))
        .detailFooter(cmp.line())
        .pageFooter(Templates.footerComponent)
        .noData(Templates.createTitleComponent("NoData"), cmp.text("There is no data"))
        .setDataSource(c)
        .toPdf(new FileOutputStream("report4.pdf")); // we are not breaking the chain

or:

JasperReportBuilder report = report()
    .setTemplate(Templates.reportTemplate)
    .columns(
       col.column("Item", "item", type.stringType()),
       col.column("Quantity", "quantity", type.integerType()),
       col.column("Unit price", "unitPrice", type.bigDecimalType()))
    .title(Templates.createTitleComponent("CollectionDatasource"))
    .detailFooter(cmp.line())
    .pageFooter(Templates.footerComponent)
    .noData(Templates.createTitleComponent("NoData"), cmp.text("There is no data"))
    .setDataSource(c); // we are created design, set styles and datasource and so on for our builder

report.toPdf(new FileOutputStream("report4.pdf"));  // we are using the valid builder prepared at previous step

Details

It is just a builder pattern, no magic here.

Let's look at source code of DynamicReports.report() method.

public class DynamicReports {
    // some members

    public DynamicReports() {
    }

    public static JasperReportBuilder report() {
        return new JasperReportBuilder();
    }

As you can see that the new object created every time we call DynamicReports.report() method. There is no singleton or static member here.

Question:

I am a little bit stuck with such an easy problem. I am using DynamicReports and I want to hide whole row if column value is null. As I know, DynamicReports is based on JasperReports and it's possible there to do that by checking TextField's option "Remove line when blank". How can I do that in Dynamic?

Components, which I use:

TextColumnBuilder, ColumnGroupBuilder, JasperReportBuilder

I want to hide whole row if any of my TextColumns would be null.


Answer:

OK, after some thoughts, I found that this problem could be resolved in other way.

We gonna use column, group etc property setPrintWhenExpression(DRIExpression expression)

1. Create class, which will handle, print or not to print the row. Dynamic has the abstract class for doing this:

    public class ShowExpressionDynamicReports extends AbstractSimpleExpression<Boolean> {

    private String fieldName;

    public ShowExpressionDynamicReports(String fieldName) {
        this.fieldName = fieldName;
    }

    @Override
    public Boolean evaluate(net.sf.dynamicreports.report.definition.ReportParameters reportParameters) {
        return reportParameters.getValue(fieldName) != null;
      }
    }

You should extend AbstractSimpleExpression in order to pass it as parameter to methods which are listed below.

So, the column value is printed if evaluate(ReportParameters rp) returns true.

I've also added field fieldName which allows me to print (or not) column due to other's column state.

2. Add property to your

column:

setPrintWhenExpression(DRIExpression expression)

group:

.setPrintSubtotalsWhenExpression(DRIExpression expression)

or

setFooterPrintWhenExpression(DRIExpression expression)

or

setHeaderPrintWhenExpression(DRIExpression expression)

Depends on what you want to hide.

Example:

We have 2 columns in our report: Product and ProductCount columns. I would like to hide Product column if ProductCount is null (we have no information for this Product).

So, to do that i will add property PrintWhenExpression to Product column

TextColumnBuilder<String> productColumn = col.column("Product", "Product", type.stringType())
.setPrintWhenExpression(new ShowExpressionDynamicReports("ProductCount"));

Question:

I am using jasper reports to generate a report. I am trying to group all the records of an item under one name. But the item names are displayed multiple type in a report

My Code is

// TODO Auto-generated method stub\\
    Logger.getLogger(getClass()).info("In Sales report servlet");
    String from = request.getParameter("from");
    String to = request.getParameter("to");
    System.out.println("From "+from+" To "+to);
    Connection connection = null;
     String connectionURL = "jdbc:mysql://localhost:3306/medicaminventory";
    try {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection(connectionURL, "root", "");
        StyleBuilder boldStyle         = stl.style().bold(); 

        StyleBuilder boldCenteredStyle = stl.style(boldStyle)

                                            .setHorizontalAlignment(HorizontalAlignment.CENTER);

        StyleBuilder columnTitleStyle  = stl.style(boldCenteredStyle)

                                            .setBorder(stl.pen1Point())

                                            .setBackgroundColor(Color.LIGHT_GRAY);

        StyleBuilder CenteredStyle = stl.style().setHorizontalAlignment(HorizontalAlignment.CENTER);
        StyleBuilder titleStyle         = stl.style(boldStyle).setFontSize(15);
        JasperReportBuilder report = DynamicReports.report();//a new report
        TextColumnBuilder<Integer> rowNumberColumn = col.reportRowNumberColumn("No.");
        TextColumnBuilder<java.util.Date> columndate = col.column("Date", "Date_Of_Sale", type.dateType()).setStyle(CenteredStyle);
        TextColumnBuilder<String>    columnItem = col.column("Item Name", "Item_Name", type.stringType()).setStyle(boldStyle);
        TextColumnBuilder<String>    columnCustomer = col.column("Customer Name", "Customer_name", type.stringType()).setStyle(CenteredStyle);
        TextColumnBuilder<Double>    columnunit = col.column("Unit Price", "Item_Price", type.doubleType()).setStyle(CenteredStyle);
        TextColumnBuilder<Integer>    columnqty = col.column("Qty", "Item_qty", type.integerType()).setStyle(CenteredStyle);
        TextColumnBuilder<BigDecimal>    columnsub = columnqty.multiply(columnunit).setTitle("Subtotal").setStyle(CenteredStyle);
        report
          .columns(
                  rowNumberColumn,columnItem,columnCustomer,columndate,columnunit,columnqty,columnsub
                  )
          .title(//title of the report
              Components.text("Sale Report").setStyle(titleStyle))
              .setColumnTitleStyle(columnTitleStyle)
              .highlightDetailEvenRows()

              .pageFooter(Components.pageXofY().setStyle(boldCenteredStyle))//show page number on the page footer
              .setDataSource(createDataSource(from,to));      

        report.groupBy(columnItem).show();



    } 
    catch(DRException e)
    {
        e.printStackTrace();
    }
    catch (SQLException e1) {
        e1.printStackTrace();

    } catch (ClassNotFoundException e) {
        e.printStackTrace();

    }


private JRDataSource createDataSource(String from, String to) {

    Connection connection = null;
     String connectionURL = "jdbc:mysql://localhost:3306/medicaminventory";
     DRDataSource dataSource = new DRDataSource("Item_Name","Customer_name", "Date_Of_Sale", "Item_Price", "Item_qty");
     ResultSet rs1 = null;
     try
     {

            Class.forName("com.mysql.jdbc.Driver");
            // Get a Connection to the database
            connection = DriverManager.getConnection(connectionURL, "root", "");
            //Add the data into the database
             Statement stmt;
                     stmt=connection.createStatement();
                rs1=stmt.executeQuery("SELECT * FROM tbl_sale WHERE Date_Of_Sale >= '"+from+"' AND Date_Of_Sale <= '"+to+"'");
                rs1.beforeFirst();
                while(rs1.next())
                {
                    dataSource.add(rs1.getString("Item_Name"), rs1.getString("Customer_name"), rs1.getDate("Date_Of_Sale"), rs1.getDouble("Item_Price"), rs1.getInt("Item_qty"));

                }
                System.out.println("Done with while");

     }
     catch (SQLException e1) {
            e1.printStackTrace();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();

        }
     finally {
        // Always close the database connection.
                        try {
                            if (connection != null) connection.close();
                            }
                    catch (SQLException ignored){
                            }
                    }
     return dataSource;

       } 

My Output

I want one item name and all the records belonging to that item under that item name.


Answer:

****Answering my own question*********

If the records in the database are random(which depends on database design) you need to order them by using ORDER BY Clause in SQL query

In this Case

Instead of

SELECT * FROM tbl_sale WHERE Date_Of_Sale >= '"+from+"' AND Date_Of_Sale <= '"+to+"'

The Query should be

SELECT * FROM tbl_sale WHERE Date_Of_Sale >= '"+from+"' AND Date_Of_Sale <= '"+to+"' ORDER BY item_name

where item_name is the name of a column in database

Question:

Is there any way to set logarithmic scale for x axis and y axis.

I have added code below for reference which I used to create chart.

XyLineChartBuilder lineBuilder = DynamicReports.cht.xyLineChart()
    .setTitle(reportSection.getGraphName())
    .setTitleFont(boldFont)
    .setXValue(xColumn)
    .series(yAxisLineSeries)
    .setXAxisFormat(DynamicReports.cht.axisFormat()
    .setLabel(reportSection.getxAxisCaption()))
    .setYAxisFormat(DynamicReports.cht.axisFormat()
    .setLabel(reportSection.getyAxisCaption()))
    .setDataSource(createDataSource(reportSection, noOfYaxis));

Answer:

I tried with base 10 and base 2, but both didn't plot negative values.

LogarithmicAxis provides a setAllowNegativesFlag() method, which may be set "true to allow negative values in data," or "false to be able to plot positive values arbitrarily close to zero." I've adapted this example to illustrate the effect.

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogarithmicAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @See https://stackoverflow.com/a/53912014/230513
 * @see https://stackoverflow.com/a/22450677/230513
 * @see https://stackoverflow.com/a/10353270/230513
 */
public class Test {

    private static final int N = 10;

    private void display() {
        XYSeries series = new XYSeries("Series");
        for (int i = -N; i <= N; i++) {
            series.add(i, i);
        }
        LogarithmicAxis xAxis = new LogarithmicAxis("X");
        xAxis.setAllowNegativesFlag(true);
        LogarithmicAxis yAxis = new LogarithmicAxis("Y");
        yAxis.setAllowNegativesFlag(true);
        XYPlot plot = new XYPlot(new XYSeriesCollection(series),
            xAxis, yAxis, new XYLineAndShapeRenderer(true, false));
        JFreeChart chart = new JFreeChart(
            "Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, false);

        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(700, 400);
            }
        });
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test().display();
            }
        });
    }
}

Question:

I am using Dynamic Reports, for generating reports. I need to know if I can use the Group Name and create a footer to the group. The footer is not subtotal, but something like a warning and description. The Groups I have are Alarm names like 'Warning Light is turned on' followed by details about the places it is turned on. The footer has to indicate the solution like 'Turn the heater off'. Below are the solutions I tried:

  • If I use a Group footer with an Expression (switch case of Alarm Names and hardcoded strings), the expected warning message gets attached to the previous Group. How to write an expression to get the current Group name?
  • If I use DynamicReports.sbt, it is shown only under one column. How to span it across multiple columns?

I am new to Dynamic Reports, any help is appreciated. Thanks.


Answer:

Solved.

  • Add a new detail to the Datasource, which has the Solution strings like ' like 'Turn the heater off' corresponding to each Alarm name. Initial Datasource: ('Alarm_Name','Place_Name'). Current Datasource: ('Alarm_Name', 'Place_Name','Solution').
  • Add a new Field called 'Solution' pointing to the solution in the datasource.
  • Create a text component with the field 'Solution'.
  • Add the component to the group footer.

Question:


Answer:

Use a parameter to reference the relative (or absolute) path to the styles file. The main report, for example, might contain:

<template><![CDATA[$P{P_REPORT_STYLES_PATH} + "FontStyle.jrtx"]]></template>
<parameter name="P_REPORT_BASE" class="java.lang.String">
    <defaultValueExpression><![CDATA[""]]></defaultValueExpression>
</parameter>
<parameter name="P_REPORT_RESOURCES_PATH" class="java.lang.String">
    <defaultValueExpression><![CDATA[$P{P_REPORT_BASE} + "resources/"]]></defaultValueExpression>
</parameter>
<parameter name="P_REPORT_STYLES_PATH" class="java.lang.String">
    <defaultValueExpression><![CDATA[$P{P_REPORT_RESOURCES_PATH} + "styles/"]]></defaultValueExpression>
</parameter>

This allows the report in iReport (or Jaspersoft Studio) to reference a relative path to the report styles, such as:

resources/styles/FontStyle.jrtx

This path is relative to the report's .jasper file location.

Then, in DynamicJasper, you can pass in a report parameter. The API call in DynamicJasper might not match the API call for the following JasperReports Library call, but it should be sufficiently similar to get the idea across:

    reportParameters.put("P_REPORT_BASE", "/home/user/dev/reports/workspace");
    JasperFillManager.fillReport(..., reportParameters, dataSource);

Assuming that /home/user/dev/reports/workspace is the location for the .jasper files as well as the workspace location for iReport/Jaspersoft Studio, then both DynamicJasper and the report development environment will find and use the same styles file.

The full path to the styles file, in this example, would be:

/home/user/dev/reports/workspace/resources/styles/FontStyle.jrtx

Your directory paths, of course, will differ.


At this point, you can reference the same styles in both environments. See also:

Question:

I am trying to generate a report using DynamicReports library. The datasource is based on the SQL query having where clause with parameter(s). In the example below, I have set the parameter "orderNo=123456". However, when I run the query, I get an exception as below.

The example shared in the DynamicReports site databasedatasourcereport does not have where clause with parameters. Please suggest what needs to be done to resolve the issue.

Exception:

Query parameter not found : orderNo
at net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign(JRAbstractCompiler.java:280) ~[jasperreports-6.8.0.jar:6.8.0-2ed8dfabb690ff337a5797129f2cd92902b0c87b]
at net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:152) ~[jasperreports-6.8.0.jar:6.8.0-2ed8dfabb690ff337a5797129f2cd92902b0c87b]
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:358) ~[jasperreports-6.8.0.jar:6.8.0-2ed8dfabb690ff337a5797129f2cd92902b0c87b]
at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:618) ~[jasperreports-6.8.0.jar:6.8.0-2ed8dfabb690ff337a5797129f2cd92902b0c87b]
at net.sf.dynamicreports.jasper.builder.JasperReportBuilder.toJasperReport(JasperReportBuilder.java:291) ~[dynamicreports-core-5.1.0.jar:na]

Source code:

JasperReportBuilder jasperReportBuilder = report().columns(col.column("Order No", "orderNo", type.stringType()))
        .columns(col.column("Order Amount", "orderAmount", type.bigDecimalType()))
        .setQuery("select orderNo, orderAmount from orders where orderNo=$P{orderNo}",
                QueryLanguage.SQL)
        .setConnection(connection).setDefaultFont(stl.font(DEFAULT_FONT, false, false, 12))
        .setParameter("orderNo", "123456")
        .pageFooter(Components.pageXofY());
JasperPrint jp = jasperReportBuilder.toJasperPrint();

Answer:

The solution is very simple - the parameter should be declared.

All you need is to add parameter definition:

 .addParameter("orderNo", String.class)

The full code will be:

JasperReportBuilder jasperReportBuilder = report()
    .columns(col.column("Order No", "orderNo", type.stringType()),
            col.column("Order Amount", "orderAmount", type.bigDecimalType()))
    .setQuery("SELECT orderNo, orderAmount FROM orders WHERE orderNo=$P{orderNo}",
            QueryLanguage.SQL)
    .setConnection(connection).setDefaultFont(stl.font(DEFAULT_FONT, false, false, 12))
    .addParameter("orderNo", String.class) // Parameter declaration (of String type)
    .setParameter("orderNo", "123456")
    .pageFooter(Components.pageXofY())
    .show();

Question:

I have created a report using dynamic reports and add a page number component and set its horizontal Alignment as right. But in printed report, page number doesn't seem to be fully right aligned.

Check this image to see the alignment issue

Note :- No right padding for page number and no trailing white spaces in page number expression.

versions used :- dynamicreports - 3.0.2 jasperreports - 4.8.0


Answer:

After lots of time spent on debugging and checking source code of dynamic reports I found the issue. I am posting this for anyone who find its helpful.

When we add PageXofYBuilder, what dynamic reports actually doing is create two text fields for 'x' and 'y'. If the component is right aligned then text field for 'x' is right aligned and text field for 'y' is left aligned with fixed width. The width of text field for 'y' is calculated as width required for a 6 digit number based on the selected font, font size and horizontal padding.

Check out the below code of pageXofY method in the class ComponentTransform which is responsible for creating the page number field in jasper design for more details :

 private DRDesignList pageXofY(DRIPageXofY pageXofY, DefaultStyleType    defaultStyleType) throws DRException {
        TemplateTransform templateTransform = accessor.getTemplateTransform();
        DRIReportStyle pageXofYStyle = pageXofY.getStyle();
        if (pageXofYStyle == null) {
            pageXofYStyle = accessor.getTemplateTransform().getTextStyle();
        }
        DRDesignStyle style = accessor.getStyleTransform().transformStyle(pageXofYStyle, true, defaultStyleType);
        Integer height = templateTransform.getPageXofYHeight(pageXofY, style);
        HorizontalAlignment horizontalAlignment = templateTransform.getPageXofYHorizontalAlignment(pageXofY, style);

        DRStyle newStylePageX = new DRStyle();
        newStylePageX.setParentStyle(pageXofYStyle);
        newStylePageX.getPadding().setRight(0);
        DRPen pen = new DRPen();
        pen.setLineWidth(0f);
        newStylePageX.getBorder().setRightPen(pen);
        DRStyle newStylePageY = new DRStyle();
        newStylePageY.setParentStyle(pageXofYStyle);
        newStylePageY.getPadding().setLeft(0);
        newStylePageY.getBorder().setLeftPen(pen);

        DRTextField<String> pageXField = new DRTextField<String>();
        pageXField.setAnchorNameExpression(pageXofY.getAnchorNameExpression());
        pageXField.setBookmarkLevel(pageXofY.getBookmarkLevel());
        pageXField.setHyperLink((DRHyperLink) pageXofY.getHyperLink());
        pageXField.setPrintWhenExpression(pageXofY.getPrintWhenExpression());
        pageXField.setStyle(newStylePageX);
        pageXField.setHeight(height);
        pageXField.setHeightType(pageXofY.getHeightType());
        pageXField.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        pageXField.setValueExpression(new PageXofYNumberExpression(pageXofY.getFormatExpression(), 0));

        DRTextField<String> pageYField = new DRTextField<String>();
        pageYField.setAnchorNameExpression(pageXofY.getAnchorNameExpression());
        pageYField.setBookmarkLevel(pageXofY.getBookmarkLevel());
        pageYField.setHyperLink((DRHyperLink) pageXofY.getHyperLink());
        pageYField.setPrintWhenExpression(pageXofY.getPrintWhenExpression());
        pageYField.setStyle(newStylePageY);
        pageYField.setHeight(height);
        pageYField.setHeightType(pageXofY.getHeightType());
        pageYField.setHorizontalAlignment(HorizontalAlignment.LEFT);
        pageYField.setValueExpression(new PageXofYNumberExpression(pageXofY.getFormatExpression(), 1));
        DRIGroup pageYEvaluationGroup = accessor.getGroupTransform().getFirstResetPageNumberGroup();
        if (pageYEvaluationGroup == null) {
            pageYField.setEvaluationTime(Evaluation.REPORT);
        }
        else {
            pageYField.setEvaluationTime(Evaluation.GROUP);
            pageYField.setEvaluationGroup((DRGroup) pageYEvaluationGroup);
        }

        int pageXofYWidth = templateTransform.getPageXofYWidth(pageXofY, style);
        switch (horizontalAlignment) {
        case LEFT:
            int pageXWidth = StyleResolver.getFontWidth(style, 4);
            int pageYWidth = pageXofYWidth - pageXWidth;
            if (pageYWidth <= 0) {
                pageYWidth = 10;
            }
            pageXField.setWidth(pageXWidth);
            pageXField.setWidthType(ComponentDimensionType.FIXED);
            pageYField.setWidth(pageYWidth);
            pageYField.setWidthType(pageXofY.getWidthType());
            break;
        case RIGHT:
            pageYWidth = StyleResolver.getFontWidth(style, 6);
            pageXWidth = pageXofYWidth - pageYWidth;
            if (pageXWidth <= 0) {
                pageXWidth = 10;
            }
            pageXField.setWidth(pageXWidth);
            pageXField.setWidthType(pageXofY.getWidthType());
            pageYField.setWidth(pageYWidth);
            pageYField.setWidthType(ComponentDimensionType.FIXED);
            break;
        default:
            pageXField.setWidth(pageXofYWidth / 2);
            pageXField.setWidthType(pageXofY.getWidthType());
            pageYField.setWidth(pageXofYWidth / 2);
            pageYField.setWidthType(pageXofY.getWidthType());
            break;
        }

        DRList listPageXofY = new DRList();
        listPageXofY.addComponent(pageXField);
        listPageXofY.addComponent(pageYField);
        return list(listPageXofY, DefaultStyleType.TEXT, null, null);
    }

StyleResolver.getFontWidth() method

protected static int getFontWidth(DRDesignStyle style, int columns) {
        double width = getFont(style).getStringBounds("m", context).getWidth();
        return (int) Math.ceil(width * columns) + getHorizontalPadding(style);
    }

Question:

I need to get the column right under the title and i don't need any gaps in between. And how to set width to the column? I have given setWidth(50) but its not getting and the border is covering entire right side of the page

Here is my code:

public class DynamicReport {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                        "jdbc:mysql://localhost:3306/marketing_database","root","root");
        } catch (SQLException e) {
            e.printStackTrace();
            return;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }

        JasperReportBuilder report = DynamicReports.report();//a new report
        StyleBuilder plainStyle = stl.style().setFontName("FreeUniversal");

        StyleBuilder boldStyle = stl.style(plainStyle).bold().setBorder(stl.pen1Point());
        StyleBuilder col1style = stl.style().setBorder(stl.pen1Point());

        report
          .title(Components.text("Tax Invoice Cum Delivery Challan").setStyle(boldStyle)
          .setHorizontalAlignment(HorizontalAlignment.CENTER))
          .columns(col.column("", "companyName", type.stringType()).setWidth(50).setStyle(col1style))
          .pageFooter(Components.pageXofY())
          .setDataSource("SELECT companyName FROM marketing_database.company_profile", 
                                      connection);
        try {
            report.show();
            report.toPdf(new FileOutputStream("c:/report.pdf"));
        } catch (DRException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
      }
}

Any help in this will be appreciated

UPDATED:

I got how to set the width for a column. I used this code:

 col.column("", "companyName", type.stringType()).setFixedWidth(20)

Answer:

report



        .columnHeader(//title of the report


              Components.text("Tax Invoice Cum Delivery Challan").setStyle(boldStyle).setFixedHeight(10)
              .setHorizontalAlignment(HorizontalAlignment.CENTER))

             .columns(
                     col.column("", "companyName", type.stringType()).setFixedWidth(200).setStyle(col1style))

              .pageFooter(Components.pageXofY())//show page number on the page footer
              .setDataSource("SELECT companyName FROM marketing_database.company_profile", 
                                      connection);

        try {
                    //show the report
            report.show();

                    //export the report to a pdf file
            report.toPdf(new FileOutputStream("c:/report.pdf"));
        } catch (DRException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
      }

Question:

I am using DynamicReports to generate a report in PDF,XLS,DOC. But my database columns are in "varchar" datatype. So when I am using those fields in generating DynamicReports there is every other datatype other than varchar. I need varchar datatype because my column consists of commas, fullstops, numbers like these. So is there any option to convert or to get the datatype as varchar.

Here is my code:

public class DynamicReport {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                        "jdbc:mysql://localhost:3306/marketing_database","root","root");
        } catch (SQLException e) {
            e.printStackTrace();
            return;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }

        JasperReportBuilder report = DynamicReports.report();//a new report
        StyleBuilder plainStyle = stl.style().setFontName("FreeUniversal");

        StyleBuilder boldStyle = stl.style(plainStyle).bold().setBorder(stl.pen1Point());

        report
          .columns(
              Columns.column("Contact Person", "Contact_Person", DataTypes.stringType()))
          .title(//title of the report
                  Templates.createTitleComponent("Fonts"),
              Components.text("FreeUniversal").setStyle(boldStyle)
              .setHorizontalAlignment(HorizontalAlignment.CENTER))
              .pageFooter(Components.pageXofY())//show page number on the page footer
              .setDataSource("SELECT Contact_Person FROM marketing_database.lead", 
                                      connection);

        try {
            report.show();
            report.toPdf(new FileOutputStream("c:/report.pdf"));
        } catch (DRException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
      }
}

Any help in this will be appreciated


Answer:

Since Dynamic Reports is based on Java, you can use the String data type for VARCHAR db types, as @AlexK and @KarthikeyanVaithilingam suggested.

CHAR, VARCHAR, and LONGVARCHAR could have been mapped to either String or char[], but String is more appropriate for normal use. Also, the String class makes conversions between String and char[] easy: There is a method for converting a String object to a char[] and also a constructor for turning a char[] into a String object.

Source

Question:

I created a report with dynamic columns using dynamic reports. If any column in the last row is overflows then the only the overflowing column is stretched and printed on next page. Rest of the columns is not stretched.

The printed report is look like this:

Following section of code is used for creating report with dynamic columns.

JasperReportBuilder jasperReportBuilder=DynamicReports.report();
for(Field field:fields){
    for (Entry<String, String> entry : dynamicTableColumns.entrySet()) {
        if ( entry.getKey().equals(field.getName())){
            jasperReportBuilder.columns(DynamicReports.col.column(entry.getValue(), field.getName().toString(), DynamicReports.type.stringType()).setStretchWithOverflow(true));
        }
    }
}

I haven't seen any option to set the column's stretch type as RELATIVE_TO_TALLEST_OBJECT. Is there any other way to fix this ?


Answer:

Setting detail's split type as 'PREVENT' will prevent the row from stretching to next page and move the entire row to next page.

jasperReportBuilder.setDetailSplitType(SplitType.PREVENT);