Para modificar la consulta de un DataSet puedes utilizar la sección “Property Binding”

en mi caso necesitaba reemplazar en la conulta el valor de un parámetro.

Para reemplazar una cadena con otra lo puedes hacer en el “Expression Builder” de la siguiente manera



var q=new Packages.java.lang.String("SELECT COUNT(*) AS TOTAL \
FROM @OFICINA.EMPLEADOS A, @OFICINA.PUESTOS R, \
@OFICINA.SALARIOS D, @OFICINA.DEPTOS O \
WHERE A.NID_ACO_EXP= R.NID_ACO \
R.NID_DMD=D.NID_DMD AND R.NORDEN=O.NID_ORDEN \
AND TRUNC(R.FECHA) BETWEEN :INICIO AND :FIN");
q.replaceAll("@OFICINA",params["OFICINA"].value);

el código es javascript, pero podemos utilizar clases Java también. En este caso utilizamos la clase String de Java en vez de Javascript, porque el método de javascript no reemplaza todas las coincidencias.

Fuentes:
birt exchange

Anuncios

Cuando tienes varios reportes, es buena idea crear una librería para reutilizar elementos en los reportes. Un ejemplo común es cuando necesitamos usar el mismo encabezado y pie de página para los reportes.

BIRT nos permite agregar algunos elementos dinámicos -tales como el número de páginas, la fecha e incluso un valor obtenido mediante código javascript en un DynamicText- El problema es que esto dependerá de cada reporte, así que ¿cómo agregamos elementos dinámicos desde una librería a nuestro reporte?

Pues habrá que crear una “master page” en la librería donde pongamos elementos “DynamicText” en el encabezado y que estos desplieguen el valor de un parámetro. Después podemos modificar el valor del parámetro en cada reporte, y así, tener un título personalizado pero manteniendo el formato.

Si además, queremos obtener el título mediante una consulta a la base de datos. Lo que tenemos que hacer es crear el DataSource a la base de datos y un DataSet con la consulta que obtiene el título, por ejemplo


SELECT DESCRIPCION
FROM OFICINAS
WHERE ID=:OFICINA

Luego, debemos poner el siguiente código en el evento “beforeFactory” de nuestro reporte


//public final static int MODE_GENERATION = 1; //This mode is for generate the report document. Typically used in Report Engine run task
//public final static int MODE_PRESENTATION = 2; //This mode is for present data that saved in report document, without further data manipulation operation. Typically used in report engine render task
//public final static int DIRECT_PRESENTATION = 3;//This mode is to execute the data query without create report document. It is used in report engine runAndRender task.
//public final static int MODE_UPDATE = 4; //This mode is used to update the existing report document with new queries. Typicially used in IV.
importPackage( Packages.org.eclipse.birt.report.model.api );
importPackage(Packages.java.lang);
importPackage(Packages.java.util);
importPackage(Packages.org.eclipse.birt.report.data.adapter.api);
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
var myconfig = reportContext.getReportRunnable().getReportEngine().getConfig();
var des = DataRequestSession.newSession(myconfig, new DataSessionContext(3));
var dsrc = reportContext.getDesignHandle().findDataSource("dsrcOficina");
var dset = reportContext.getDesignHandle().findDataSet("dsetOficina");
des.defineDataSource(des.getModelAdaptor().adaptDataSource(dsrc));
des.defineDataSet(des.getModelAdaptor().adaptDataSet(dset));
var paramBinding = new InputParameterBinding("param_1", new ScriptExpression("\""+ params['IDOFICINA'].value +"\"") );
queryDefinition = new QueryDefinition( );
queryDefinition.setDataSetName( "dsetOficina" );
queryDefinition.addInputParamBinding( paramBinding );
queryDefinition.setAutoBinding(true);
var pq = des.prepare( queryDefinition );
var qr = pq.execute( null );
var ri = qr.getResultIterator( );
if ( ri.next( ) )
{
params["Titulo"].value = ri.getString("DESCRIPCION");
}
ri.close( );
qr.close( );
des.shutdown( );

Es importante poner los nombres exactamente igual que en el diseñador.
En nuestro caso, el parámetro “IDOFICINA” es de tipo String, así que lo ingresamos de la siguiente manera


var paramBinding = new InputParameterBinding( "param_1",new ScriptExpression("\""+ params['IDOFICINA'].value +"\"") );

si fuera un Integer tendría que ser de la siguiente manera


var paramBinding = new InputParameterBinding( "param_1",new ScriptExpression(params['IDOFICINA'].value) );

El valor de ScriptExpression debe ser un bloque de javascript válido, cómo si lo ingresaramos en la ventana “ExpressionBuilder” 🙂

Fuentes:
eclipse forums
birt exchange

Al crear un DataSet con una consulta con parámetros, BIRT me arrojaba el error

org.eclipse.birt.data.engine.core.DataException: Failed to prepare the query execution for the data set: t_host
Cannot get the type for parameter: 1.
org.eclipse.birt.report.data.oda.jdbc.JDBCException: Cannot get parameter type.
SQL error #1:Unsupported feature

Al parecer el problema sólo se presenta con la base de datos de Oracle y ha sido resuelto a partir de la versión 4.2.1 de BIRT. Así que, si tienes una versión anterior, basta con actualizar para resolver el problema (Help->Check for Updates).

Fuentes:
eclipse forums

Cuando estás diseñando un reporte es muy útil la pestaña de “Preview” para ver los cambios que estás haciendo y probar que todo funcione correctamente.

Con Eclipse for Java Developers versión “Juno” en Ubuntu 12.04 a 64 bits abrí un reporte que tenía y al dar clic en Preview me arrojó el error:

Unhandled event loop exception No more handles [Unknown Mozilla path (MOZILLAFIVEHOME not set)]

Encontré este post que explica el problema y la forma de solucionarlo. Desafortunadamente a mi no me funcionó la solución. Intenté con diferentes versiones de XULRunner -cabe destacar que xulrunner a 64 bits sólo lo encontré a partir de la versión 5.0- y también intenté la opción de utilizar WebKit pero tampoco funcionó.

A veces Eclipse se cerraba de forma inesperada y en la consola registraba el siguiente error

[000:000] Browser XEmbed support present: 1
[000:000] Browser toolkit is Gtk2.
[000:000] Using Gtk2 toolkit
[000:000] Warning(optionsfile.cc:47): Load: Could not open file, err=2
[000:000] No bp log location saved, using default.
[000:001] Browser XEmbed support present: 1
[000:001] Browser toolkit is Gtk2.
[000:001] Using Gtk2 toolkit

Finalmente encontré una solución alterna al problema. Al agregar la opción “-Dorg.eclipse.swt.browser.DefaultType=mozilla” al archivo eclipse.ini y dar clic en Preview, Eclipse muestra el mensaje “Internal browser is not available” pero abre mi navegador por default (Chrome) y muestra el reporte 😀

Para publicar los reportes creados con BIRT en un servidor de aplicaciones no hay nada más fácil que utilizar el Report Viewer. En JBoss AS7 es tan sencillo como copiar el archivo birt.war -que viene con el BIRT Runtime– en el directorio {$as7home}/standalone/deployments, abrir el archivo birt.war y agregar el reporte que deseas.

Una vez hecho esto, abres el navegador y accedes a http://localhost:8080/birt/frameset?__report=rptSentenciasPendientes.rptdesign
Obviamente tienes que cambiar el parámetro “__report” por el nombre de tu reporte. Listo, ya deberías ver tu reporte!

En mi caso me arrojaba el error

org.eclipse.birt.report.engine.api.EngineException: Can not load the report query: 104. Errors occurred when generating the report document for the report element with ID 104. (Element ID:104)
    at org.eclipse.birt.report.engine.data.dte.DataPresentationEngine.doExecuteQuery(DataPresentationEngine.java:160)
    at org.eclipse.birt.report.engine.data.dte.AbstractDataEngine.execute(AbstractDataEngine.java:267)
    at org.eclipse.birt.report.engine.executor.ExecutionContext.executeQuery(ExecutionContext.java:1905)

Supe entonces que había un problema al ejecutar una consulta. Recordé que los datos provienen de una base de datos de Oracle y por lo tanto necesitaba colocar el controlador de la base de datos, ojdbc6.jar, en el directorio WEB-INF/lib.

Con ello los errores desaparecieron y el reporte se generó correctamente.

En los reportes que creó con BIRT tengo un encabezado “estándar” que utiliza el valor de un parámetro para desplegar el título.
Hace poco me tope con un título que contenía acentos y noté que en vez de “Archivo Histórico” me ponía “Archivo HistÃ3rico”.

Para pasar un parámetro con acentos al ReportViewer, y que este lo despliegue correctamente, necesitas primero sustituir los carácteres acentuados por su entidad html correspondiente y luego codificar la url (yo utilizo la función URL.encodeQueryString() de GWT)

url.append("Titulo1=").append(URL.encodeQueryString(escapeHTML(tituloOficina)));

Para escapar el html tuve que crear mi propia función ya que los métodos StringUtil.asHTML() y SafeHtmlUtils.htmlEscape() no sustituyen los caracteres acentuados.

public static final String escapeHTML(String s) {
		StringBuffer sb = new StringBuffer();
		int n = s.length();
		for (int i = 0; i < n; i++) {
			char c = s.charAt(i);
			switch (c) {
			// á &aacute;
			case 225:
				sb.append("á");
				break;
			// Á &Aacute;
			case 193:
				sb.append("Á");
				break;
			// é &eacute;
			case 233:
				sb.append("é");
				break;
			// É &Eacute;
			case 201:
				sb.append("É");
				break;
			// í &iacute;
			case 237:
				sb.append("í");
				break;
			// Í &Iacute;
			case 205:
				sb.append("Í");
				break;
			// ó &oacute;
			case 243:
				sb.append("ó");
				break;
			// Ó &Oacute;
			case 211:
				sb.append("Ó");
				break;
			// ú &uacute;
			case 250:
				sb.append("ú");
				break;
			// Ú &Uacute;
			case 218:
				sb.append("Ú");
				break;

			default:
				sb.append(c);
				break;
			}
		}
		return sb.toString();
	}

actualización (16/10/2017)

en el ejemplo anterior se realiza la codificación y paso de parámetros mediante GWT. Recientemente tuvimos el mismo problema pero en una aplicación con javascript y angular.

Para realizar el mismo proceso en javascript utilizamos la librería he.js (que también codifica los caracteres con acentos) para codificar primero a HTML y luego, la función [encodeURIComponent], para codificar a los caracteres permitidos en la URL.

url += '&Titulo3=' + encodeURIComponent(he.encode($scope.reporte.descripcion, {decimal: true}))
windows.open(url)

notesé el parámetro {decimal: true} en la función he.encode, que es necesario para que BIRT viewer lo decodifique correctamente.

para entender porque se utiliza la función encodeURIComponent en vez de encodeURI, puedes ver este post

Fuentes:
birt-exchange forum
string-functions.com – html encode
meyerweb.com – URL decoder/encoder

En el título de un reporte necesitaba poner el valor de un párametro, el detalle es que el párametro está enlazado a un DataSet, por lo tanto tiene un value y un displayText. En mi caso es un listado de oficinas, cada una tiene su clave y su nombre, p. ej. BIBL – BIBLIOTECA
Si pongo un DynamicText en el encabezado con el valor
params[“OFICINA”].displayText //despliega BIBLIOTECA
pero únicamente cuando genero el reporte desde Eclipse o en el Report Viewer con la operación “frameset”.
En mi aplicación tengo un botón para imprimir el reporte, que únicamente abre el enlace

http://jboss.midominio.com:8080/ReportViewer/run?__format=pdf&__report=rptInformeMensual.rptdesign&OFICINA=BIBL

para generar el reporte en un documento PDF.
El problema es que en el título, en vez de mostrar “BIBLIOTECA” me aparece el texto “NULL”.
Cómo de todos modos tengo el título de la oficina seleccionada en mi aplicación, decidí enviarla como un parámetro extra y así no tuve ningún problema.
La URL finalmente quedó así
http://jboss.midominio.com:8080/ReportViewer/run?__format=pdf&__report=rptInformeMensual.rptdesign&OFICINA=BIBL&TITULO=BIBLIOTECA
y mi DynamicText del encabezado
params[“TITULO”];

Si tu parámetro es de selección multiple (multi-select) tal vez te interesa ver esto.