martes, 21 de abril de 2015

Ideas de reporting con xDocReport y Gx-Java

Algo que me motiva es hacer aplicaciones que tengan opciones de configuración potentes, que den a los usuarios buenas posibilidades de ajustarse a diferentes escenarios, a cambiantes contextos de negocios. O sea, a lo que tenemos por estos tiempos, cada día.
Tengo la idea de que cada vez es más común y aceptado que usuarios de configuración dispongan de más recursos en este sentido, de tal forma que los sistemas se puedan ajustar y adaptar rápido a determinados cambios. Por ejemplo, cuando se necesita definir un producto nuevo o cuando cambian reglas de cálculo de una nómina.
Otra veta a explotar en este camino es el reporting. En este post les cuento un poco sobre xDocReport, una api Java que nos permite trabajar con templates diseñados por cualquier usuario, usando MS Word, insertando campos de "combinación de correspondencia" (mergefields) que asumirán los valores de un xml al momento de crear el reporte. Usaremos la sintaxis de FreeMarker para los campos en el template docx.

Bueno, lo primero: Descargar xDocReport desde aquí.
Luego crear una KB GX-Java (yo usé la XEv2) con un webpanel que llame a un procedure, copiar todos los Jar a la carpeta web y setear la Path List de la siguiente forma:


A continuación preparar el template con MS Word.
Debe quedar más o menos así:


Dejé resaltados los campos para que se aprecie bien, así que no esperen que el archivo les quede exactamente igual. Los campos se crean usando Ctrl-F9 y se completan con la opción "Editar Campo" que aparece con el click derecho. Ahí deben dejarlo de tipo MergeField y en el nombre poner el identificador o directiva que corresponda (por ejemplo ${doc.project.name}).


El xml lo podemos generar con un sdt y el método ToXml, pero en este ejemplo lo pondremos en un archivo:
<devs>
    <developer>
        <devname>ZERR</devname>
        <devlastname>Angelo</devlastname>
        <devmail>angelo.zerr@gmail.com</devmail>
    </developer>           
    <developer>
        <devname>Leclercq</devname>
        <devlastname>Pascal</devlastname>
        <devmail>pascal.leclercq@gmail.com</devmail>
    </developer>           
</devs>           
El siguiente sería el código del procedure:

&tmpString = !"C:" + chr(92) + "xDocReportFiles" + chr(92)
&fileIN  = &tmpString + !"xDocRptTemplate.docx"
&fileXml = &tmpString + !"xDocRptData.xml"
&fileOUT = &tmpString + !"xDocRptOut.docx"
java try {
// 1) Load Docx file by filling  template engine and cache it to the registry
java     java.io.InputStream in = new java.io.FileInputStream([!&fileIN!]);
java     fr.opensagres.xdocreport.document.IXDocReport report;
java     fr.opensagres.xdocreport.template.TemplateEngineKind kind = fr.opensagres.xdocreport.template.TemplateEngineKind.Freemarker;
java     report = fr.opensagres.xdocreport.document.registry.XDocReportRegistry.getRegistry().loadReport(in,kind);
// 2) Create context Java model
java     fr.opensagres.xdocreport.template.IContext context = report.createContext();
java     java.io.InputStream projectInputStream = new java.io.FileInputStream([!&fileXml!]);
java     org.xml.sax.InputSource projectInputSource = new org.xml.sax.InputSource( projectInputStream );
java     freemarker.ext.dom.NodeModel project = freemarker.ext.dom.NodeModel.parse( projectInputSource );
java     context.put( "doc", project );
// 3) Generate report by merging Java model with the Docx
java     java.io.OutputStream out = new java.io.FileOutputStream(new java.io.File([!&fileOUT!]));
java     report.process(context, out);
java     } catch (Exception e) {
java         System.out.println("Exception thrown: " + e);
java     e.printStackTrace();
java }
RESULTADO
Para ejecutar, asegurarse de que los archivos estén en el directorio que corresponda, especialmente los Jar que deben estar en la "lib" de nuestra aplicación en el Tomcat.
Si todo sale bien, aparecerá nuestro report con los datos provistos por el xml y debiera verse así:



Eso, por ahora.

Queda una lista interesante de cosas por hacer: generar data con SDTs/DataProviders, queries dinámicas con "For Xml" (usando un store proc en Sql Server), convertir a Pdf, convertir las librerías para poder usarlas con Gx-Csharp, etc..

salu2!!!

4 comentarios:

  1. Interesante Miguel!
    Una sugerencia: ya que la solución es casi 100% código nativo, se podría encapsular la parte java nativa del código en un external object y llamarlo desde el procedure. De esa forma, el mismo external object podría apuntar a la implementación Java o .NET en el caso que tenga mi solución genearda para ambos lenguajes.

    ResponderEliminar
  2. Hola!
    Sí, claro. No he tenido experiencia con eso, pero es el camino ideal a seguir.
    Escribir un java que exponga las cosas que nos interesa usar en gx y luego usarlo como EO.
    Da para postear algo al "respective", no?.
    Igual un poco se trata de cosas que a mí me gustaría que gx ya las tuviera. Yo sólo escribo de cómo hacerlas con lo primero que tengo a mano.
    salu2!!!

    ResponderEliminar
  3. Hola,

    Esto podría usarse con Linux con el OpenOficce?

    Gracias

    ResponderEliminar
  4. Hola Oscar

    Así tal como lo publiqué está pensado para crear los templates con MSWord, pero por tratarse de una solución GX+Java debe trabajar sin problemas en cualquier servidor de servlets, sobre Linux o sobre lo que sea, independiente de cómo creaste las plantillas.
    He estado muy corto de tiempo para postear, pero me dejaste la idea de poner una actualización sobre el tema, esta vez con templates ODT (OpenOffice!!) que también están soportadas por XDocReport.

    salu2!!!

    ResponderEliminar