Exportar tabla ADF a excel (II)

Le he echado un vistazo al artículo Export ADF Table To Excel de iAdvise y he conseguido reproducirlo. Para el ejemplo he usado la tabla EMPLOYEES del esquema HE que viene con la instalación de Oracle XE, pero como veréis sirve cualquier tabla.
Lo primero es crear el objeto de entidad (opcional) y el correspondiente objeto de vista:

Al final debería haber un árbol de objetos de modelo como éste:

Ahora crearemos una clase de utilidad con el método de ejemplo que he tomado y retocado de iAdvise:

package com.tsoracle.util;

import java.io.IOException;
import java.io.PrintWriter;

import java.util.Date;

import javax.faces.context.FacesContext;

import javax.servlet.http.HttpServletResponseWrapper;

import oracle.adf.model.binding.DCIteratorBinding;

import oracle.jbo.Row;
import oracle.jbo.RowSetIterator;


/**
 * tsoracle.com
 * Clase de utilidades de transformación
 */
public class TransformUtil {

    public TransformUtil() {
    }

    /**
     * Método tomado y adaptado de iAdvise, de su artículo 
     * "Export ADF Table To Excel" del 11 de Abril de 2007. http://iadvise.blogspot.com/2007/04/export-adf-table-to-excel.html
     * Este método coge una tabla ADF cualquiera y devuelve al usuario su contenido
     * en una hoja excel
     * 
     * @param tableContent Tabla con el contenido
     * @throws IOException 
     */
    public static void exportHtmlTableToExcel(DCIteratorBinding tableContent) throws IOException {

        //Set the filename DateTime dt = new
        Date ahora = new Date();

        // El nombre habría que tratar de hacerlo pseudoúnico de una mara más fina
        String filename = ahora.toString() + ".csv";


        //Setup the output 
        String contentType = "application/vnd.ms-excel";
        FacesContext fc = FacesContext.getCurrentInstance();
        HttpServletResponseWrapper response = 
            (HttpServletResponseWrapper)fc.getExternalContext().getResponse();
        response.setHeader("Content-disposition", 
                           "attachment; filename=" + filename);

        response.setContentType(contentType);
        PrintWriter out = response.getWriter();

        // Obtengo el iterador de la tabla
        RowSetIterator rsi = tableContent.getRowSetIterator();

        String[] attNames = rsi.getRowAtRangeIndex(0).getAttributeNames();

        // Pinta el título de las columnas
        for (int i = 0; i < attNames.length; i++) {

            out.print(attNames[i] + ";");

        }

        out.println();
        
        // Obtengo el índice del registro actual
        Row filaSeleccionada = rsi.getCurrentRow();
        
        // Me posiciono en el primer registro
        rsi.first();
        
        Row currentRow;
        // Itero por todas las filas
        while ((currentRow = rsi.getCurrentRow()) != null) {
            Object[] attValues = currentRow.getAttributeValues();
            
            // Recorro cada columna y escribo su valor
            for (int j = 0; j < attValues.length; j++) {

                out.print(attValues[j] + ";");

            }

            out.println();

            // Muevo el iterador hacia delante
            rsi.next();
        }
        out.close();

        // Finaliza el fichero
        fc.responseComplete();
        
        // Vuelvo a dejar al iterador posicionado donde lo encontré, para evitar errores
        // de "cambio de divisa"
        rsi.setCurrentRow( filaSeleccionada );

    }

}

El siguiente paso es crear una nueva página y arrastrar sobre ella el objeto de vista como una ADF Read Only Table:

Ahora creamos un nuevo CommandButton en el footer de la tabla:

Lo siguiente es colocarse sobre el inspector de propiedades del botón y pinchar sobre los puntos suspensivos del ActionListener:

Entonces aparece un asistente preguntándonos bean y método. Creamos un nuevo bean (AdfTable2ExcelPageBean) y dentro de él un nuevo método (exportToExcel). Al final en la propiedad ActionListener tendremos el valor #{AdfTable2ExcelPageBean.exportToExcel}:

Antes de seguir hay que agregar la propiedad bindings al código de la clase del bean:

/**
 * Variable que contiene los bindings
 */
protected BindingContainer bindings;

public void setBindings(BindingContainer bindings) {
    this.bindings = bindings;
}

public BindingContainer getBindings() {
    return bindings;
}

Y tampoco podemos olvidarnos de inicializar la variable en el fichero faces-config.xml:

  
    AdfTable2ExcelPageBean
    com.tsoracle.adftable2excel.view.backing.AdfTable2Excel
    request
    
      bindings
      #{bindings}
    
  

O si lo preferimos, podemos hacerlo con los asistentes que nos proporciona el entorno. Primero creamos un nuevo managed value:

Y luego, pinchando sobre el botón Edit, el valor:

Ahora queremos que el método que hemos creado en el ActionListener obtenga el iterador de la tabla y se lo pase a la función estática. Tenemos que ver en primer lugar cómo se llama el iterador. Para ello pulsamos con el botón derecho sobre una zona vacía de la página y le damos a Go to Page Definition:

Luego buscamos el iterador:

Y nos quedamos con su nombre:

Ahora ya podemos rellenar el código del método exportToExcel, tal como se explica en iAdvise:

/**
 * Método que transforma los datos de la tabla a excel.
 */
public void exportToExcel(ActionEvent actionEvent) throws IOException {
    TransformUtil.exportHtmlTableToExcel((DCIteratorBinding)bindings.get("EmployeesView1Iterator"));
}

Finalmente ejecutamos y probamos el botón:

Por si a alguien le interesa he subido el ejemplo. Después de descomprimirlo es necesario copiar las librerías adf-faces-impl.jar, jsf-impl.jar a WEB-INF/lib: AdfTable2Excel.zip.

Anuncios