Birt:从 beforeFactory 访问数据集的内容

Birt: access content of dataset from beforeFactory

本文关键字:数据集 访问 beforeFactory Birt      更新时间:2023-09-26

我试图(拼命地)通过 beforeFactory 中的脚本访问数据集的内容。

手头的任务是从链接库创建设计元素,并将它们放置在网格的某个单元格中。除了"将它们放在网格的某个单元格中"部分之外,一切正常。

有关要创建哪个元素以及放置该元素的位置的信息可在数据集 (dsDesignInformation) 中找到,该数据集包含三列:targetRow、targetColumn、targetContent。 targetContent 包含一个字符串,用于在库中查找元素。

例如:主体上放置了一个网格(grdMasterGrid),有两行两列。如果 dsDesignInformation 包含类似 (1,1,"testObjectName") 的行,我想从链接库中创建元素 "testObject" 并将其放置在 grdMasterGrid 的第 1 行和第 1 列的交集。

用于创建和放置元素的代码:

importPackage(org.eclipse.birt.report.model.api);
var myLibraryHandle = reportContext.getDesignHandle().getLibrary("myLibraryName");
var myElementFactory = reportContext.getDesignHandle().getElementFactory();
// should be the objectname as defined in the dsDesignInformation 
var myTargetElementHandle = myLibraryHandle.findElement("testObjectName");
var myCreatedElementHandle = myElementFactory.newElementFrom(myTargetElementHandle , "someUniqueElementName");
var myMasterGridHandle = reportContext.getDesignHandle().findElement("grdMasterGrid");
// should be target coordinates as defined in dsDesignInformation 
var myTargetCellHandle= myMasterGridHandle.getCell(1,1);
myTargeCellHandle.getContent().add(myCreatedElementHandle);

当与硬编码的目标信息一起使用并放置在报表设计的 beforeFactory 中时,这就像一个超级按钮。

但是,我确实需要访问dsDesignInformation的内容并将它们传递给上面的脚本。到目前为止(4 天后),我的成功率为零(如空)。

我很高兴能得到有关该主题的任何帮助或想法。

问候马格古茨

可以这样做,但有一些严格的限制。

主要限制是:不能直接使用数据源和数据集。相反,您必须复制它们并使用副本。不要问我为什么会这样,因为我不知道。但我在数小时和数天的尝试中以艰难的方式学会了它......

下一个限制是:很遗憾,您无法访问报表参数值。如果您的查询在没有参数的情况下工作,这不是问题。否则,无论如何,您都必须找到一种方法来访问参数值。例如,根据报表集成到应用中的方式,可以在调用 BIRT 之前尝试将值写入应用上下文。

下面是一段工作代码(在 beforeFactory 事件中),向您展示如何解决此限制:

importPackage( Packages.org.eclipse.birt.report.model.api );
importPackage(Packages.org.eclipse.birt.data.engine.api);
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
importPackage(Packages.org.eclipse.birt.data.engine.core);
importPackage( Packages.org.eclipse.birt.report.model.api );
var myconfig = reportContext.getReportRunnable().getReportEngine().getConfig();
var de = DataEngine.newDataEngine( myconfig, null );
var dsrc = reportContext.getDesignHandle().findDataSource("lisa");
// This is the existing data source.
var odaDataSource = new OdaDataSourceDesign( "Test Data Source" );
// We create a new DataSource which is only to be used in this event
// Now we copy the relevant properties from the existing DataSource to the new one.
var dbUrl = dsrc.getProperty("odaURL").toString();
var dbUsr = dsrc.getProperty("odaUser").toString();
var dbPwd = dsrc.getProperty("odaPassword").toString();
var dbDrv = dsrc.getProperty("odaDriverClass").toString();
odaDataSource.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc" );
odaDataSource.addPublicProperty( "odaURL", dbUrl );
odaDataSource.addPublicProperty( "odaDriverClass", dbDrv);
odaDataSource.addPublicProperty( "odaUser", dbUsr );
odaDataSource.addPublicProperty( "odaPassword", dbPwd );        
// log.info("odaURL=" + dbUrl); // Only if you have a logging framework at hand
// Now create a new DataSet and set its query etc.
// I suppose that it is possible to copy the properties from an existing DataSet instead.
//  However, I didn't try that.
var odaDataSet = new OdaDataSetDesign( "Test Data Set" );
odaDataSet.setDataSource( odaDataSource.getName() );
odaDataSet.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" );
// This is the SQL query (in my application).
// You'll have to modify this as needed.
odaDataSet.setQueryText( " select STEDA.TEDA_ID, STBST.LANGTEXT" +
                     " from STEDA, STBST" +
                     " where STEDA.ZUSATZ_1 = 'MATRIX'" +
                     " and STBST.TBST_ID = STEDA.TEDA_ID"); 
// Tell the DataEngine about the new objects.
de.defineDataSource( odaDataSource );
de.defineDataSet( odaDataSet );
// Now execute the query:
// This seems overly complicated, but hey: it works.
var queryDefinition = new QueryDefinition( );
queryDefinition.setDataSetName( odaDataSet.getName() );
queryDefinition.setAutoBinding(true);
var pq = de.prepare( queryDefinition );
var qr = pq.execute( null );
rowcount=0;     
var elementFactory = reportContext.getDesignHandle().getElementFactory()
var ri = qr.getResultIterator( );       
// Our application is using the query to generate a layout structure 
// into an (already existing) placeholder element "Layout MATRIX".
var containerGrid = reportContext.getDesignHandle().findElement("Layout MATRIX");
// Iterate through the query results
while (  ri.next( ) )
{
    // get the actual values of the query output columns
    var tedaId = ri.getString("TEDA_ID");
    var langtext = ri.getString("LANGTEXT");
    // log.info("langtext: " + langtext);
    rowcount++;
    // Do something with the current result row.
    ... myModifyLayout(containerGrid, tedaId, langtext); ...
}
// Cleanup
ri.close( );
qr.close( );
de.shutdown( );
// You may want to save the modified design file while developing.
// That way you can check the mresults in the Report Designer.
if (false) {
    reportContext.getDesignHandle().saveAs("c:/temp/modified.rptdesign");
}