Scriptlets de Jasper Reports

La diferencia entre los informes de iReports realizados para Openbravo y Open ERP es que para Openbravo se realizan directamente sobre consultas SQL en la base de datos, y en Open ERP se utiliza el módelo de datos exportado en xml usando el lenguaje xPath como vimos en los post anteriores. En los informes que hacemos sobre SQL es mas o menos fácil filtrar y transformar esos datos si conoces el lenguaje, si usas el lenguaje xPath para filtrar o transformar esos datos es necesario usar Scriptlets. En este post voy a mostrar como realizar un Scriptlet y usarlo en iReports.

Un Scriptlet para Jasper Reports es una clase Java que hereda de JRDefaultScriptlet, los métodos que creemos en esta clase estarán disponibles para usarlos en nuestro informe.

Para crear este Scriptlet de ejemplo vamos a crear un fichero llamado CalendarioScriptlet.java en un directorio llamado calendario, con dos métodos, uno que dice el día de la semana en el que cae el día uno de un mes y el otro método dice el número de días que tiene un mes.

Este es el código:

package calendario;
import net.sf.jasperreports.engine.JRAbstractScriptlet;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;
import java.util.*;
public class CalendarioScriptlet extends JRDefaultScriptlet {
public Integer primerDiaMes(String mes, String anno) throws JRScriptletException{
Calendar cal = new GregorianCalendar();
cal.set(Integer.parseInt(anno), Integer.parseInt(mes)-1, 1);
int num = cal.get(Calendar.DAY_OF_WEEK );
return num;
}
public Integer numeroDiaMes(String mes, String anno) throws JRScriptletException{
Calendar cal = new GregorianCalendar();
cal.set(Integer.parseInt(anno), Integer.parseInt(mes)-1, 1);
cal.add(Calendar.MONTH, 1);
cal.add(Calendar.DATE, -1);
int num = cal.get(Calendar.DAY_OF_MONTH );
return num;
}
}

Esta es la clase que hemos creado para usar en nuestro informe, para poder usarlo tenemos que compilar el java. Para poder compilar el scriptlet tienes que tener las librerías de jasperreports, puedes descargarlo desde aquí, busca el .jar.

Si nos situamos en el directorio padre del directorio calendario en el que esta CalendarioScriptlet.java, y tienes la librería de jasper en /home/usuario/report/jasperreports-3.7.2.jar puedes compilar así:

javac -classpath /home/usuario/report/jasperreports-3.7.2.jar calendario/CalendarioScriptlet.java

y puedes crear la librería .jar de tu Scriptlet así:

jar cf calendarioScriptlet.jar calendario/CalendarioScriptlet.class

Con esto tenemos calendarioScriptlet.jar.

Ahora vamos a ver lo que tenemos que hacer en iReport para poder usar el Scriptlet. Primero vamos a las propiedades del informe.

Aquí tenemos que asegurarnos que el lenguaje es Java y poner la clase del Scriptlet.

Y en el campo import poner también el nombre de la clase.

Ahora vamos a Herramientas>Opciones para añadir al classpath nuestra librería, para poder ejecutarlo en iReport. Podemos añadir al classpath directamente calendarioScriptlet.jar o el directorio que lo contiene, si queremos ejecutar el informe desde otro programa tendremos que copiar la librería al PATH del sistema o copiarla junto con el resto de las librerías.

Con esto ya podemos usar las clases de nuestro Scriptlet en el informe, podemos usarlo por ejemplo en un field, teniendo en cuenta que el tipo de dato que devuelve sea el mismo que el tipo de dato del field o haciendo algún tipo de casting, o podemos usarlo para filtrar los datos, clickando el botón «Filter expression…» en la ventana de la consulta del informe.

Para llamar a un método de nuestra clase tenemos que llamarla sobre el parámetro $P{REPORT_SCRIPTLET}, por ejemplo para conocer el número de días de el mes de febrero del año 2010 lo podemos hacer así:
$P{REPORT_SCRIPTLET}.numeroDiaMes("2","2010")

Con esto hemos visto como crear y usar un Scriptlets en iReports, este Scriptlet en concreto lo he creado para realizar un informe tipo calendario así que pronto subiré otro post con la explicación del informe y el ejemplo de como usar este Scriptlet.

21 comentarios sobre “Scriptlets de Jasper Reports

  1. gpt

    Hola, una consulta:

    Sigo todo el procedimiento correctamente, pero al ejecutar el informe desde OpenERP obtengo un error:

    Fault:

    Agradeceré mucho tu ayuda. Saludos.

  2. Angel Moya Autor del artículo

    Hola, ¿el log de OpenERP solo muestra «fault:»? ¿puedes pasarme la traza completa? ¿lo has probado en iReport?

  3. Gilson

    Hola que tal, estoy usando jdeveloper 10g, y he creado el scriptlet, ya hice todos los pasos anteriores, ya tengo el jar importado en el IReport, pero al compilar mi reporte desde el iReport(v3.7) me sale java.lang.ClassNotFoundException: view.backing.fac.FacturacionScriptlet
    ojala pudieras ayudarme muchas gracias!

  4. Angel Moya Autor del artículo

    Hola, pues el error ese parece que es porque no esta encontrando la clase, copia el jar en un sitio accesible, puedes copiarlo en el directorio lib de iReports, o ponerlo en algun directorio accesible desde el path del sistema… a ver si hay suerte.

  5. Gilson

    Hola Angel ya lo he solucionado esa parte, ahora el problema es que no llama al metodo de la clase del Scriptlet, no se por que pasa eso,
    esta es mi clase con el metodo
    public class FacturacionScriptlet extends JRDefaultScriptlet {

    public static BigDecimal getImpuesto(String codDocu, BigDecimal numFact, BigDecimal numItem,
    String producto,String esquema){
    System.out.println(«entro en public String getImpuesto «);
    BigDecimal monto = new BigDecimal(0);
    EsqdetFcr_rImpl instanciaEsquemaDetalle = getEsquemaDetalle(codDocu,numFact,numItem,producto,esquema);
    Row r = instanciaEsquemaDetalle.first();
    monto.add((BigDecimal)r.getAttribute(«MontoTotal»));

    return new BigDecimal(«123»);

    }
    private static EsqdetFcr_rImpl getEsquemaDetalle(String codDocu, BigDecimal numFact, BigDecimal numItem,
    String producto,String esquema){
    System.out.println(«entro en private EsqdetFcr_rImpl getEsquemaDetalle «);
    AppMoFacturacionImpl imple = new AppMoFacturacionImpl();
    EsqdetFcr_rImpl instanciaEsquemaDetalle = imple.getEsqdetFcr_r1();
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vCodDocu»,codDocu);
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vNumFact»,numFact);
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vNumItem»,numItem);
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vProducto»,producto);
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vEsquema»,esquema);
    instanciaEsquemaDetalle.setNamedWhereClauseParam(«vCondicion»,»IVA»);
    instanciaEsquemaDetalle.executeQuery();
    return instanciaEsquemaDetalle;

    }

    ojala puedas ayudarme gracias

  6. Gilson

    que raro es esto, le saque todos los parametros al metodo,y solo le puse que retorne un Hola Mundo y tampoco me pinta nada en el reporte 🙁

  7. Gilson

    que locura es esto, resulta que estoy usando un scriptlet en un campo de un subreporte que esta en el Detail, pero en el Detail no me pintaba nada, si en el Page Header

  8. Angel Moya Autor del artículo

    Hola Gilson, he tenido mucho lio esta semana y no había podido ponerme con mi blog hasta ahora… de todas formas no se si voy a poder ayudarte, los scriptlets los he usado poco.

    Una cosa, el informe devuelve otros datos… es decir en el datail hay datos, si la consulta sobre la que iteras no devuelve datos puede que sea por eso por lo que no te muestra nada en el detail.

  9. Lu

    Hola!
    Estoy tratando de generar un reporte y seria mas facil si pudiera pasarle como parametro a una funcion del scriplet un parametro o un campo del reporte…es posible? Alguien sabe como hacerlo? Las pruebas que he hecho no han funcionado…
    Ojala puedan ayudarme
    Gracias!

  10. Angel Moya Autor del artículo

    Hola, lo siento pero no he vuelto a utilizar scriptlets y no se si voy a poder ayudarte, si estas usando openerp te recomiendo que prepares los datos en openerp y luego montes el informe sobre los datos organizados.

  11. Jonathan Guacaran

    Un codigo para quienes se interesen, realizado con la información presentada en esta pagina y otras busquedas.

    <<<<<<<>>>>>>>>>>>>>

    package montoescrito;

    import net.sf.jasperreports.engine.JRAbstractScriptlet;
    import net.sf.jasperreports.engine.JRDefaultScriptlet;
    import net.sf.jasperreports.engine.JRScriptletException;
    import java.util.*;
    import java.text.DecimalFormat;
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.text.NumberFormat;

    public class n2t extends JRDefaultScriptlet {

    private int flag;
    public int numero;
    public int numero_entero;
    public double decimales;
    public int decimales_entero;
    public String texto;
    public String importe_parcial;
    public String num;
    public String num_letra;
    public String num_letras;
    public String num_letram;
    public String num_letradm;
    public String num_letracm;
    public String num_letramm;
    public String num_letradmm;

    public n2t(){
    numero = 0;
    flag=0;
    }
    public n2t(int n){
    numero = n;
    flag=0;
    }

    private String unidad(int numero){

    switch (numero){
    case 9:
    num = «nueve»;
    break;
    case 8:
    num = «ocho»;
    break;
    case 7:
    num = «siete»;
    break;
    case 6:
    num = «seis»;
    break;
    case 5:
    num = «cinco»;
    break;
    case 4:
    num = «cuatro»;
    break;
    case 3:
    num = «tres»;
    break;
    case 2:
    num = «dos»;
    break;
    case 1:
    if (flag == 0)
    num = «uno»;
    else
    num = «un»;
    break;
    case 0:
    num = «»;
    break;
    }
    return num;
    }

    private String decena(int numero){

    if (numero >= 90 && numero 90)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 90));
    }
    else if (numero >= 80 && numero 80)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 80));
    }
    else if (numero >= 70 && numero 70)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 70));
    }
    else if (numero >= 60 && numero 60)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 60));
    }
    else if (numero >= 50 && numero 50)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 50));
    }
    else if (numero >= 40 && numero 40)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 40));
    }
    else if (numero >= 30 && numero 30)
    num_letra = num_letra.concat(«y «).concat(unidad(numero – 30));
    }
    else if (numero >= 20 && numero = 10 && numero = 100)
    {
    if (numero >= 900 && numero 900)
    num_letra = num_letra.concat(decena(numero – 900));
    }
    else if (numero >= 800 && numero 800)
    num_letra = num_letra.concat(decena(numero – 800));
    }
    else if (numero >= 700 && numero 700)
    num_letra = num_letra.concat(decena(numero – 700));
    }
    else if (numero >= 600 && numero 600)
    num_letra = num_letra.concat(decena(numero – 600));
    }
    else if (numero >= 500 && numero 500)
    num_letra = num_letra.concat(decena(numero – 500));
    }
    else if (numero >= 400 && numero 400)
    num_letra = num_letra.concat(decena(numero – 400));
    }
    else if (numero >= 300 && numero 300)
    num_letra = num_letra.concat(decena(numero – 300));
    }
    else if (numero >= 200 && numero 200)
    num_letra = num_letra.concat(decena(numero – 200));
    }
    else if (numero >= 100 && numero = 1000 && numero = 2000 && numero <10000){
    flag=1;
    num_letram = unidad(numero/1000).concat(" mil ").concat(centena(numero%1000));
    }
    if (numero 10000 && numero = 20000 && numero <100000){
    flag=1;
    num_letradm = decena(numero/1000).concat(" mil ").concat(miles(numero%1000));
    }

    if (numero = 100000 && numero <1000000){
    flag=1;
    num_letracm = centena(numero/1000).concat(" mil ").concat(centena(numero%1000));
    }
    if (numero = 1000000 && numero = 2000000 && numero <10000000){
    flag=1;
    num_letramm = unidad(numero/1000000).concat(" millones ").concat(cienmiles(numero%1000000));
    }
    if (numero 10000000 && numero = 20000000 && numero <100000000){
    flag=1;
    num_letradmm = decena(numero/1000000).concat(" milllones ").concat(millon(numero%1000000));
    }

    if (numero 0 ) {
    texto = Integer.toString(decimales_entero);
    if ( decimales_entero < 10 )
    texto = "0"+texto;
    }
    num_letras = decmillon(numero_entero)+" con "+texto+"/100";
    return num_letras;
    }

    }

  12. Dina

    Hola Cuando compilo el .jrxml en ireport no me hace el import de NumerosLetras, indica «The import NumerosLetras cannot be resolved» esto no permite generar el .jasper… puede ayudarme, orientarme que puedo hacer?

  13. Naitsir

    Buenas Angel, disculpa que te moleste, espero puedas ayudarme.
    Encontré este articulo para aniadir unas librerias jar a ireport y crear imagenes con codigo qr
    https://www.colino.net/wordpress/archives/2013/10/09/adding-qrcode-to-jasper-reports-ireport-the-easy-way/

    una vez creado el reporte lo añado a openerp, pero obtengo el siguiente error, a pesar de añadir las librerias a la ruta de mis librerias en java x:\jre\lib\ext e incluso añadi las librerías a la carpeta de librerias del modulo …addons\jasper_reports\java\lib
    y aun asi openerp me devuelve el siguiente error

    Report Error

    Failed to invoke method execute in class com.nantic.jasperreports.JasperServer: Byte data not found at location : BufferedImage@1a390b3: type = 12 IndexColorModel: #pixelBits = 1 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@1d3707a transparency = 1 transIndex = -1 has alpha = false isAlphaPre = false BytePackedRaster: width = 300 height = 300 #channels 1 xOff = 0 yOff = 0

  14. Pingback: Intro a jasper report, generar reporte con parámetros. | coronado EDGAR

  15. Pingback: Escribir numeros a letras en Jasper Report | miguel angel meca pacherres

  16. Felipe Montoya

    Disculpen no entiendo muy bien como crearlo me pueden ayudar con un paso a paso para jasperreports o como hacer paso a paso para poder tener los números en letras muchas gracias mi correo es montoyauranchristian@hotmail.com

  17. Ovidio

    Muchas gracias, me fue muy útil el blog. Gracias a ti no fue tan difícil de implementar.

  18. jj

    Alguien a trabajado en jasper report con XML lenguaje de consulta Xpath, todo funcion ok en el cliente pero al publicarlo en el servidor de jasper no funciona bien que pude ser, una luz.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.