简体   繁体   English

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

[英]Birt: access content of dataset from beforeFactory

Im trying (desperately) to access the content of a dataset by script in the beforeFactory. 我试图(拼命)通过beforeFactory中的脚本访问数据集的内容。

The task at hand is to create design elements from a linked library and place them in a certain cell of a grid. 当前的任务是从链接的库中创建设计元素,并将其放置在网格的特定单元格中。 Everything works fine except for the "place them in a certain cell of a grid"-part. 除了“将它们放置在网格的特定单元格中”部分之外,其他所有东西都工作正常。

The information about which element is to be created and where it is to be placed is available in a dataset (dsDesignInformation), which contains three columns: targetRow, targetColumn, targetContent. 有关要创建哪个元素以及将其放置在何处的信息在数据集(dsDesignInformation)中可用,该数据集包含三列:targetRow,targetColumn,targetContent。 targetContent contains a string, which is used to find an element in the library. targetContent包含一个字符串,用于在库中查找元素。

For example: There is a grid placed on the body (grdMasterGrid), with two rows and two columns. 例如:主体上有一个网格(grdMasterGrid),具有两行两列。 If the dsDesignInformation would contain a row like (1,1,"testObjectName"), I want to create the element "testObject" from a linked library and place it in the intersection of row 1 and column 1 of my grdMasterGrid. 如果dsDesignInformation将包含类似(1,1,“ testObjectName”)的行,我想从链接库中创建元素“ testObject”,并将其放置在grdMasterGrid的第1行和第1列的交集处。

The code for creating and placing the element: 用于创建和放置元素的代码:

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);

This works like a charm when used with hard coded target-information and placed in the beforeFactory of the report design. 当与硬编码的目标信息一起使用并放在报表设计的beforeFactory中时,这就像一种魅力。

I do however need to access the contents of dsDesignInformation and pass them on to the script above. 但是,我确实需要访问dsDesignInformation的内容,并将它们传递给上面的脚本。 So far (4 days in) I had zero (as in null) success. 到目前为止(4天之内),我获得了零成功(无效)。

I would be glad for any help or ideas on the topic. 对于该主题的任何帮助或想法,我将感到高兴。

Regards, maggutz 问候,maggutz

It is possible to do this, but with some severe restrictions. 可能做到这一点,但也有一些严格的限制。

The main restriction is: You cannot use your DataSource and your DataSet directly. 主要限制是:您不能直接使用DataSource和DataSet。 Instead, you'll have to copy them and work with the copy. 相反,您必须复制它们并使用副本。 Don't ask my why this is, because I don't know. 不要问我为什么会这样,因为我不知道。 But I learned it the hard way during hours and days of trying... 但是我在数小时甚至数天的尝试中都很难学到它。

The next restriction is: You cannot access report parameter values, unfortunately. 下一个限制是:很遗憾,您无法访问报告参数值。 This is not a problem if your query works without parameters. 如果您的查询没有参数,这不是问题。 Otherwise, you'll have to find a way to access the parameter value anyhow. 否则,您将必须找到一种以任何方式访问参数值的方法。 Depending on how your report is integrated into the app, you could try writing the value into the appContext before calling BIRT, for example. 例如,根据将报表集成到应用程序中的方式,您可以尝试在调用BIRT之前将值写入appContext。

Here is a fragment of working code (in the beforeFactory event) to show you how to workaround this limitation: 这是工作代码的一部分(在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");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM