Dynamically add reports as subreports to a master report in BIRT
I am developing a reporting application where a user can select(and order) reports from a list of 100 reports and ask for a master report. This master report should contain all the selected reports in the exact order, with a table of contents listing the (sub)reports included in the master report and corr开发者_运维百科ect page number.
How do I accomplish this is BIRT? I was using Pentaho before this and was able to accomplish the same there by adding each user selected report as a subreport at runtime(i.e. programmatically) to a master report, which was really a place holder report.
Now I know BIRT has the notion of subreport, but I am unable to make sense of the BIRT DE API to accomplish what had earlier done with Pentaho to create a master report. So, how do I do this?
From How do I combine multiple BIRT reports, it seems that this was not possible with BIRT in 2008. Is this still the case? Can't I take independent reports and add them as subreports to another report?
After some trouble, I figured how to achieve this. Basically we have to programmatically extract all the report items, data sets etc in each report and stick them in the new Master Report. After every child reoprt, I make sure a pagebreak is insert so that the next report will come on the next page. A rough code for this is :-
public class ReportGen {
private static ReportDesignHandle reportDesignHandle;
private static ElementFactory elementFactory;
private static ReportDesignHandle reportDesignHandle1;
public static void main(String[] args) {
executeReport();
}
public static void executeReport() {
IReportEngine engine = null;
EngineConfig config = null;
try {
config = new EngineConfig();
config.setBIRTHome("/home/vineeth/Softwares/birt-runtime-2_6_2/ReportEngine");
config.setLogConfig("/home/vineeth/Softwares", Level.FINEST);
Platform.startup(config);
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
engine = factory.createReportEngine(config);
IReportRunnable design = null;
//Open the report design
design = engine.openReportDesign("/home/vineeth/cash_flow_summary.rptdesign");
SessionHandle sessionHandle = DesignEngine.newSession(null);
reportDesignHandle = sessionHandle.createDesign();
elementFactory = reportDesignHandle.getElementFactory();
reportDesignHandle1 = (ReportDesignHandle) design.getDesignHandle();
DesignElementHandle cashflow = reportDesignHandle1.findElement("cashflow");
DesignElementHandle designElementHandle = reportDesignHandle1.getBody().get(0);
if (designElementHandle instanceof ExtendedItemHandle) {
ExtendedItemHandle itemHandle = (ExtendedItemHandle) designElementHandle;
ExtendedItem item = (ExtendedItem) itemHandle.getElement();
ExtendedItem newItem1 = (ExtendedItem) item.doClone(CopyForPastePolicy.getInstance());
newItem1.setName("cf1");
newItem1.setProperty(DesignChoiceConstants.CHOICE_PAGE_BREAK_AFTER, DesignChoiceConstants.PAGE_BREAK_AFTER_ALWAYS);
ExtendedItemHandle newItemHandle1 = new ExtendedItemHandle(reportDesignHandle.getModule(), newItem1);
reportDesignHandle.getBody().add(newItemHandle1);
ExtendedItem newItem2 = (ExtendedItem) item.doClone(CopyForPastePolicy.getInstance());
newItem2.setName("cf2");
newItem2.setProperty(DesignChoiceConstants.CHOICE_PAGE_BREAK_AFTER, DesignChoiceConstants.PAGE_BREAK_AFTER_ALWAYS);
ExtendedItemHandle newItemHandle2 = new ExtendedItemHandle(reportDesignHandle.getModule(), newItem2);
reportDesignHandle.getBody().add(newItemHandle2);
ExtendedItem newItem3 = (ExtendedItem) item.doClone(CopyForPastePolicy.getInstance());
newItem3.setName("cf3");
newItem3.setProperty(DesignChoiceConstants.CHOICE_PAGE_BREAK_AFTER, DesignChoiceConstants.PAGE_BREAK_AFTER_ALWAYS);
ExtendedItemHandle newItemHandle3 = new ExtendedItemHandle(reportDesignHandle.getModule(), newItem3);
reportDesignHandle.getBody().add(newItemHandle3);
DataSourceHandle dataSourceHandle = (DataSourceHandle) reportDesignHandle1.getDataSources().get(0);
DataSource ds = (DataSource) dataSourceHandle.copy();
DataSourceHandle newDSHandle = null;
if (ds instanceof OdaDataSource) {
newDSHandle = new OdaDataSourceHandle(reportDesignHandle.getModule(), ds);
}
reportDesignHandle.getDataSources().add(newDSHandle);
DataSetHandle dataSetHandle = (DataSetHandle) reportDesignHandle1.getDataSets().get(0);
OdaDataSet copyDataSetHandle = (OdaDataSet) dataSetHandle.copy();
DataSetHandle copyDSHandle = new OdaDataSetHandle(reportDesignHandle.getModule(), copyDataSetHandle);
reportDesignHandle.getDataSets().add(copyDSHandle);
}
//reportDesignHandle.getBody().add(reportDesignHandle1.getBody().get(0));
//reportDesignHandle.getBody().add(reportDesignHandle1.getBody().get(0));
IReportRunnable newDesign = engine.openReportDesign(reportDesignHandle);
IRunAndRenderTask task = engine.createRunAndRenderTask(newDesign);
HTMLRenderOption options = new HTMLRenderOption();
options.setOutputFileName("/home/vineeth/Softwares/out.html");
options.setOutputFormat("html");
task.setRenderOption(options);
task.run();
task.close();
engine.destroy();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
Platform.shutdown();
}
}
}
Rather than trying to dynamically piece reports together at runtime, it may be easier to build a master report with all 100 components in it. Then populate the bookmark property of each component (or subreport) with a value. Lastly set the visibility property of each component to "false" by default.
At runtime, when the user selects the subreports they want to see, you can pass in the desired subreports as a parameter at which point you can toggle the visibility property so only the desired subreports display.
This should be a lot easier than writing a ton of compiled code, and give you the flexibility of adding and removing subreports anytime you want without having to write any code whatsoever.
Good Luck!
精彩评论