Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
THRUST SERVICES & TOOLS
CLOUD EDITIONS
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
How is a library supposed to work anyway?
b2tech
Hello:
I thought it should be easy to mimic the functionality of copying over repeating library elements to a report design (which obviously works in the BIRT Report Designer nicely), but.......
After spending a great deal of time trying to get library elements out to a report design using only the DE, I have determined the following:
If you need to repeat an element (ie. a table contained in a library) in one report design, you will need to create a unique tablehandle for each iteration.
[Thanks jrreid]
For example:
// Get the existing element from the library that will be used more than once in the report
// TableHandle deh5 = (TableHandle) libhan.findElement("Table_HalfWidth");
// Create the first iteration of the repeating element
// TableHandle deh51 = (TableHandle) libhan.getElementFactory().newElementFrom(deh5,"Table_Iteration_One");
Then do a localize() on each ie:
deh51.localize();
deh52.localize(); etc etc.....
Not quite sure what all happens in there (localize()) but it does make it all work. So.... now I have my DE generated report, with miscellaneous elements that come from the library and upon looking at the XML code I noticed that all my library links for the duplicated table elements are NOT there (ie. extends=[back-to-library-name]) and the report has no tie-back to the library that was opened by the design engine. Am I missing something here? Is this a step that you have to do again manually? I figured that my line of code to write out the table from the library would take care of all that.
design.getBody().add(deh51);
The above line does not preserve the "extends=" that allows you to make a change to a library element that then propogates (sometimes multiple times with the same report) to possibly hundreds of report design files.
Anyone know what the logic/code should be in here?
BillH
Find more posts tagged with
Comments
JasonW
Bill,
Take a look at this example:
package DEAPI;
import java.util.logging.Level;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.model.api.DesignConfig;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.IDesignEngine;
import org.eclipse.birt.report.model.api.IDesignEngineFactory;
import org.eclipse.birt.report.model.api.LibraryHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.SessionHandle;
import org.eclipse.birt.report.model.api.TableHandle;
import com.ibm.icu.util.ULocale;
public class AddTableFromLibRef {
public void runReport() throws EngineException
{
IReportEngine engine=null;
IDesignEngine dengine=null;
EngineConfig config = null;
try{
config = new EngineConfig( );
config.setBIRTHome("C:birtbirt-runtime-2_3_2birt-runtime-2_3_2ReportEngine");
config.setLogConfig(null, Level.FINE);
config.setResourcePath("C:workworkspaces2.3.2workspacesBIRT -DE RE API SamplesAPIsresource");
Platform.startup( config );
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
engine = factory.createReportEngine( config );
DesignConfig dconfig = new DesignConfig( );
config.setBIRTHome("C:/birt/birt-runtime-2_3_2/birt-runtime-2_3_2/ReportEngine");
IDesignEngineFactory dfactory = (IDesignEngineFactory) Platform
.createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY );
dengine = dfactory.createDesignEngine( dconfig );
IReportRunnable design = null;
//Open the report design
SessionHandle session = dengine.newSessionHandle( ULocale.ENGLISH );
design = engine.openReportDesign("Reports/TopNPercent.rptdesign");
ReportDesignHandle report = (ReportDesignHandle) design.getDesignHandle( );
String libloc = report.getResourceFolder();
LibraryHandle libhan =session.openLibrary("C:workworkspaces2.3.2workspacesBIRT -DE RE API SamplesAPIsReportstest.rptlibrary");
report.includeLibrary("C:workworkspaces2.3.2workspacesBIRT -DE RE API SamplesAPIsReportstest.rptlibrary", "mylib");
DesignElementHandle deh1 = libhan.findDataSource("Data Source");
DesignElementHandle deh2 = libhan.findDataSet("Data Set");
DesignElementHandle deh3 = libhan.findElement("myTable");
DesignElementHandle ldeh1 = report.getElementFactory().newElementFrom(deh1, "newds");
DesignElementHandle ldeh2 = report.getElementFactory().newElementFrom(deh2, "newdt");
DesignElementHandle ldeh3 = report.getElementFactory().newElementFrom(deh3, "newtable");
DesignElementHandle ldeh4 = report.getElementFactory().newElementFrom(deh3, "newtable2");
report.getDataSources().add(ldeh1);
report.getDataSets().add(ldeh2);
report.getBody().add(ldeh3);
report.getBody().add(ldeh4);
report.saveAs("reports/modifiedtopnlibref2.rptdesign");
//Create task to run and render the report,
IRunAndRenderTask task = engine.createRunAndRenderTask(design);
task.setParameterValue("Top Percentage", new Integer(3));
task.setParameterValue("Top Count", new Integer(5));
task.validateParameters();
HTMLRenderOption options = new HTMLRenderOption();
options.setOutputFileName("output/desample/ModifiedTopNPercent.html");
options.setOutputFormat("html");
options.setImageDirectory("resample/images");
task.setRenderOption(options);
task.run();
task.close();
session.closeAll(false);
engine.destroy();
Platform.shutdown();
System.out.println("Finished");
}catch( Exception ex){
ex.printStackTrace();
}
}
/**
*
@param
args
*/
public static void main(String[] args) {
try
{
AddTableFromLibRef ex = new AddTableFromLibRef( );
ex.runReport();
}
catch ( Exception e )
{
e.printStackTrace();
}
}
}
Jason
b2tech
Thanks Jason,
I finally got this to work (duplicate element creation from a BIRT library) after studying your code.
What I have not figured out though is the syntax to use in the DE to change the filter condition of a table that resides "inside" of another table after that element has been added from a library to a DE created design.
In the actual library element I am duplicating, the "outer" table is using a dataset filter (determines table heading and footer text to display above/below the table by parameters passed from our custom interface) and the inner table (which displays muliple record lines) gets its dataset from the outer table. Both of these filters are in sync and have to change (together) whenever the library element is cloned into the report design.
The reason I don't use ONE table (with its header/footer areas) to display a table of data in a report is so I can dynamically grow/shrink the columns of a table (not knowing ahead of time how many columns will display within each cloned library table) The table header and footer labels need to stay "centered"* above the final report table area and need to stay together as a group for data driven showing/hiding etc. I also do this for charting areas in a report
* if you have a table with a header that has merged cells and you shrink the number of columns in that table (ie. hide columns) due to a query shrinking the number of columns returned, you will crash out when running the actual *.rptdesign. A cell spanning multiple columns in the header of a table when a column(s) are hidden dynamically causes the issue.
So when I use:
FilterCondition fc = StructureFactory.createFilterCond();
fc.setExpr( "row["Report"]" );
fc.setOperator(DesignChoiceConstants.MAP_OPERATOR_EQ);
fc.setValue1("3.0");
PropertyHandle ph =
deh51.getPropertyHandle( TableHandle.FILTER_PROP );
// Remove and change the default filter of 1 for the outside table
ph.removeItem( 0 );
// Add the new filter for the corresponding area
ph.addItem(fc); // add new filter
to change the filter condition of the "outer" table, it works for the "outer" table but does not propagate through to the "inner" table that gets its dataset from the outer table. (I would not expect it to) Since I change the filter condition AFTER my library element is cloned by the DE, how do you reference the newly created DesignElementHandle (deh51) and then go deeper in it to the inner table and change its filter also? I have tried many variations of using SlotHandle without much luck. Any thoughts here.
BillH
JasonW
Bill,
Have you tried to get a de handle on the inner table using its name?
reportContext.getDesignHandle().findElement("mytable");
Jason
b2tech
Jason:
Thanks much for you help.
For:
"reportContext.getDesignHandle().findElement("mytable");"
I tried that approach and it did not locate the inner table that resides inside of the "footer" area of the outside table. This table-within-a-table was created by the DE and was a cloned element from my BIRT library.
I did though eventually correctly walk the slots of my design and achieve what I was looking for. My final issue with using a BIRT library to create canned report elements concerns the following:
A clone of an element like:
DesignElementHandle deh41 = design.getElementFactory().newElementFrom(deh4, "HBar_FullWidth_Clone_1");
[Note: deh4 was the original handle created to the library element]
causes the expression line of some data elements (where my GUI parameters feed into) in the outer table to be blanked out in the report design. If you just take a library element and DON'T clone it, then this does not happen. So my question is, is the newElementFrom buggy? I know that jrreid also had some issues in this area.
And finally, is the DE capable of taking report parameters out of a library and then just stuffing them into a newly created report design or do you also need to load the report engine?. Let's say I have 20 parameters in a library and I just want to write them out to the new report design. I am not opening an existing design file.
BillH
JasonW
Bill,
Can you post some example code that shows the issue?
You should not need to open the report engine or an existing design to get the parameters. They should work like any other element.
Jason
b2tech
Jason:
[This is the result when you clone a library element with DE code:
ie. DesignElementHandle deh3 = libhan.findElement("Table_FullWidth");
DesignElementHandle deh31 = design.getElementFactory().newElementFrom(deh3, "Table_FullWidth_Clone_1");
The library element is a table-within-a-table.
The inner table resides within the footer line of the outside table]
<table name="Table_FullWidth_Clone_1" id="7769" extends="****_Report_Parts.Table_FullWidth">
<list-property name="boundDataColumns">
<structure>
<property name="name">Report</property>
<expression name="expression">dataSetRow["Report"]</expression>
</structure>
</list-property>
<overridden-values>
<ref-entry baseId="7389" id="7389"/>
<ref-entry baseId="7390" id="7390"/>
<ref-entry baseId="7404" name="NewData442" id="7404"/>
<ref-entry baseId="7386" id="7386"/>
<ref-entry baseId="7387" id="7387"/>
<ref-entry baseId="7395" name="Table_FullWidth1" id="7395">
<list-property name="filter">
<structure>
<property name="operator">eq</property>
<expression name="expr">row["Report"]</expression>
<simple-property-list name="value1">
<value>3.0</value>
</simple-property-list>
</structure>
</list-property>
<list-property name="boundDataColumns">
<structure>
<property name="name">Report</property>
<expression name="expression">dataSetRow["Report"]</expression>
</structure>
</list-property>
</ref-entry>
<ref-entry baseId="7415" id="7415"/>
<ref-entry baseId="7416" id="7416"/>
<ref-entry baseId="7417" id="7417"/>
...
<ref-entry baseId="7424" name="NewData11011" id="7424"/>
<ref-entry baseId="7425" id="7425"/>
<ref-entry baseId="7426" name="NewData21011" id="7426"/>
<ref-entry baseId="7427" id="7427"/>
<ref-entry baseId="7428" name="NewData31011" id="7428"/>
<ref-entry baseId="7429" id="7429"/>
<ref-entry baseId="7430" name="NewData41011" id="7430"/>
<ref-entry baseId="7431" id="7431"/>
<ref-entry baseId="7432" name="NewData5811" id="7432"/>
<ref-entry baseId="7433" id="7433"/>
<ref-entry baseId="7434" name="NewData6111" id="7434"/>
<ref-entry baseId="7435" id="7435"/>
<ref-entry baseId="7436" name="NewData7111" id="7436"/>
<ref-entry baseId="7437" id="7437"/>
<ref-entry baseId="7438" name="NewData8111" id="7438"/>
<ref-entry baseId="7439" id="7439"/>
<ref-entry baseId="7440" name="NewData9111" id="7440"/>
<ref-entry baseId="7441" id="7441"/>
<ref-entry baseId="7442" name="NewData11151" id="7442"/>
<ref-entry baseId="7443" id="7443"/>
<ref-entry baseId="7444" id="7444"/>
<ref-entry baseId="7445" id="7445"/>
<ref-entry baseId="7446" id="7446"/>
...
<ref-entry baseId="7452" name="NewData12131" id="7452"/>
<ref-entry baseId="7453" id="7453"/>
<ref-entry baseId="7454" name="NewData13111" id="7454"/>
<ref-entry baseId="7455" id="7455"/>
<ref-entry baseId="7456" name="NewData14111" id="7456"/>
<ref-entry baseId="7457" id="7457"/>
<ref-entry baseId="7458" name="NewData15111" id="7458"/>
<ref-entry baseId="7459" id="7459"/>
<ref-entry baseId="7460" name="NewData16111" id="7460"/>
<ref-entry baseId="7461" id="7461"/>
<ref-entry baseId="7462" name="NewData17111" id="7462"/>
<ref-entry baseId="7463" id="7463"/>
<ref-entry baseId="7464" name="NewData18111" id="7464"/>
<ref-entry baseId="7465" id="7465"/>
<ref-entry baseId="7466" name="NewData19111" id="7466"/>
<ref-entry baseId="7467" id="7467"/>
<ref-entry baseId="7468" name="NewData21151" id="7468"/>
<ref-entry baseId="7469" id="7469"/>
<ref-entry baseId="7470" name="NewData22131" id="7470"/>
<ref-entry baseId="7471" id="7471"/>
<ref-entry baseId="7472" id="7472"/>
<ref-entry baseId="7473" name="NewLabel7111" id="7473"/>
<ref-entry baseId="7474" id="7474"/>
<ref-entry baseId="7475" name="NewLabel8111" id="7475"/>
<ref-entry baseId="7476" id="7476"/>
<ref-entry baseId="7477" name="NewLabel9111" id="7477"/>
<ref-entry baseId="7478" id="7478"/>
<ref-entry baseId="7479" name="NewLabel10111" id="7479"/>
<ref-entry baseId="7480" id="7480"/>
<ref-entry baseId="7481" name="NewLabel11111" id="7481"/>
<ref-entry baseId="7482" id="7482"/>
<ref-entry baseId="7483" name="NewLabel12111" id="7483"/>
<ref-entry baseId="7484" id="7484"/>
<ref-entry baseId="7485" name="NewLabel13111" id="7485"/>
<ref-entry baseId="7486" id="7486"/>
<ref-entry baseId="7487" name="NewData23111" id="7487"/>
<ref-entry baseId="7488" id="7488"/>
<ref-entry baseId="7489" name="NewData24111" id="7489"/>
<ref-entry baseId="7490" id="7490"/>
<ref-entry baseId="7491" name="NewData25111" id="7491"/>
<ref-entry baseId="7492" id="7492"/>
<ref-entry baseId="7493" name="NewData26111" id="7493"/>
<ref-entry baseId="7494" id="7494"/>
<ref-entry baseId="7495" name="NewData27111" id="7495"/>
<ref-entry baseId="7496" id="7496"/>
...
<ref-entry baseId="7535" id="7535"/>
<ref-entry baseId="7536" name="NewData55111" id="7536"/>
<ref-entry baseId="7537" id="7537"/>
<ref-entry baseId="7538" name="NewData56111" id="7538"/>
<ref-entry baseId="7539" id="7539"/>
<ref-entry baseId="7540" name="NewData57111" id="7540"/>
<ref-entry baseId="7560" id="7560"/>
<ref-entry baseId="7561" id="7561"/>
<ref-entry baseId="7562" id="7562"/>
<ref-entry baseId="7563" id="7563"/>
<ref-entry baseId="7564" id="7564"/>
<ref-entry baseId="7565" id="7565"/>
<ref-entry baseId="7566" id="7566"/>
<ref-entry baseId="7567" id="7567"/>
<ref-entry baseId="7568" id="7568"/>
...
<ref-entry baseId="7549" name="NewData1501" id="7549"/>
<ref-entry baseId="7388" id="7388"/>
</overridden-values>
<list-property name="filter">
<structure>
<property name="operator">eq</property>
<expression name="expr">row["Report"]</expression>
<simple-property-list name="value1">
<value>6.0</value>
</simple-property-list>
</structure>
</list-property>
</table>
[And this is what you get in the DE report design by NOT cloning a library element with design.getElementFactory().newElementFrom.....
ie. just using DesignElementHandle deh3 = libhan.findElement("Table_FullWidth")
Notice that all the expressions come through correctly in this case if you don't use the newElementFrom in the code:
like:
<expression name="expression">if (dataSetRow["Report"] == "1") {
rhead[0]; }
else if (dataSetRow["Report"] == "2") {
rhead[1]; }........
We use parameter values generated by the user's GUI to generate all report area (ie. pie, bar, table) titles and footnotes and additionally
all 3-line individual table column headings]... so what has happened to the code that is contained within the original library element, it appears to have been dropped out?
<property name="name">Column Binding</property>
<expression name="expression">if (dataSetRow["Report"] == "1") {
rhead[0]; }
else if (dataSetRow["Report"] == "2") {
rhead[1]; }
else if (dataSetRow["Report"] == "3") {
rhead[2]; }
else if (dataSetRow["Report"] == "4") {
rhead[3]; }
else if (dataSetRow["Report"] == "5") {
rhead[4]; }
else if (dataSetRow["Report"] == "6") {
rhead[5]; }
else if (dataSetRow["Report"] == "7") {
rhead[6]; }
else if (dataSetRow["Report"] == "8") {
rhead[7]; }
else if (dataSetRow["Report"] == "9") {
rhead[8]; }
else if (dataSetRow["Report"] == "10") {
rhead[9]; }
else if (dataSetRow["Report"] == "11") {
rhead[10]; }
......etc, etc.
Bill
JasonW
Bill,
Sorry I am still confused. I just modified my library to add a table to a table footer and used the newElementFrom for the outer table and both tables and expression were added correctly. Do you have an example lib that I can use to reproduce the problem?
Jason