openxava / documentation / Report generation - Lesson 7: Multiple collections

×News: OpenXava with AI - Refine the UI (Part 2) - December 1 · Read more

Video

In this video, we will see how to create a master-detail report with multiple collections in the same report.

Any problem with this lesson? Ask in the forum

Code

You can download the project for this lesson. You can also copy the code used in the video here:

In controllers.xml file:
<controller name="Invoice">
    <extends controller="Invoicing"/>
    <action name="printInvoiceWithOrders"
	    class="com.yourcompany.invoicing.actions.PrintInvoiceWithOrdersAction"
	    mode="detail"
	    icon="printer"/>
</controller>
In PrintInvoiceWithOrdersAction.java file:
public class PrintInvoiceWithOrdersAction extends JasperReportBaseAction {

	private Invoice invoice;
	
	@Override
	protected JRDataSource getDataSource() throws Exception {
		return new JREmptyDataSource();
	}

	@Override
	protected String getJRXML() throws Exception {
		return "InvoiceWithOrders.jrxml";
	}

	@Override
	protected Map getParameters() throws Exception {
		Messages errors = MapFacade.validate("Invoice", getView().getValues());
		if (errors.contains()) throw new ValidationException(errors);
		Map parameters = new HashMap();		
		parameters.put("customerNumber", getInvoice().getCustomer().getNumber());
		parameters.put("customerName", getInvoice().getCustomer().getName());
		parameters.put("invoiceNumber", getInvoice().getNumber());
		parameters.put("date", getInvoice().getDate().toString());
		parameters.put("vatPercentage", getInvoice().getVatPercentage());
		parameters.put("vat", getInvoice().getVat());
		parameters.put("totalAmount", getInvoice().getTotalAmount());
		
		parameters.put("details", new JRBeanCollectionDataSource(getInvoice().getDetails()));
		parameters.put("orders", new JRBeanCollectionDataSource(getInvoice().getOrders()));
		
		return parameters;
	}

	private Invoice getInvoice() {
		if (invoice == null) {
			int year = getView().getValueInt("year");
			int number = getView().getValueInt("number");
			invoice = Invoice.findByYearNumber(year, number);
		}
		return invoice;
	}
	
}

Transcription

Hello, I'm Monica. In this lesson, you'll learn how to design reports for working with two or more collections, sending a JRDataSource as a parameter for each collection.

In the controllers, we create an action to print an invoice in detail mode. We'll call it printInvoiceWithOrders and link it to the action PrintInvoiceWithOrdersAction. We create this new action in the actions package and copy everything from PrintInvoiceDetailAction. We add two parameters to send: the invoice detail lines and associated orders. We’ve sent collections this way via data source; we'll do the same with parameters. We change the report name to InvoiceWithOrders, which we’ll create shortly, and return an empty data source.

Next, we create a new report called InvoiceWithOrders and copy some elements from the InvoiceDetail report. We select the title section and paste it. Here too, we copy these elements and select the column footer section to paste them there. Then we remove sections we won’t use. We add another detail section. Now we copy the parameters from InvoiceDetail and paste them into our new report's parameters. Ready, we now add a new table element to Details 1. We press next. In Dataset name, we give it a name to identify it and select create an empty dataset. We double-click on the table. We see that, like the report, we have parameters and fields. We delete lines we won’t use, leaving only the header and detail. Then we resize the table to take up the full width of the report. And we add as many columns as we need. Lastly, we add the fields by copying them directly from InvoiceDetail. We place the fields in the order we want to show and adjust the width of each column. Then we drag static text to the header line to name each column. Ready. We create another table to show the order collection associated with the invoice. We select create a table using a new dataset. We name it orders and also select create an empty dataset. We delete lines we aren’t interested in, add fields, and adjust the table. We go back to the report and create parameters to receive both collections. We sent it as JRBeanCollectionDataSource, so we will also receive it in that way. Finally, we assign each table to use the parameter as the data source.  We save. We copy the report.

We paste the report and start the application. We’ve managed to show both collections; perhaps we could improve a bit aesthetically, for example, by slightly separating the collections and showing the column footer right after the detail lines end. We expand the detail sections a bit to separate both collections. We click outside the report, then select float column footer. We save, copy the report, and restart the application. Ready.

There are many ways to display different collections in a report; we’ve seen one of them, which is sending a JRDataSource for each collection as a parameter. If you have any questions or problems, you can ask us in the forum. You can also download the lesson code in the repository link; both links are in the video description. Bye.