Varios de los reportes que manejo son simples tablas que muestran información, el inconveniente es que cada vez que se agrega, cambia o elimina alguna información debo cambiar los datos de las vistas y luego la aplicación para realizar nuevamente un deploy al servidor.
Ya he hecho y configurado tanto tablas dinámicas como formularios dinámicos a partir de una tabla de configuración, esto es muy largo y tedioso, entonces me propuse a buscar un método simple para solo mostrar información.
La idea original es: Usemos una vista para indicar tanto el título de las columnas como los datos de los registros para crear una tabla html automática, de esta manera si necesitamos agregar, cambiar o eliminar una columna o dato, lo hagamos directamente en la vista y no en la aplicación.
Digamos que tenemos una vista de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 |
CREATE OR REPLACE FORCE VIEW V_DOCUMENTOS AS SELECT ID_CLIENTE, NRO_DOC "NRO DOC.", (CASE WHEN COD = 'LO' THEN 'LOCAL' ELSE 'EXTERNO' END) "SUCURSAL", FORMATO_NUMERO(SALDO) "SALDO", FORMATO_NUMERO(CAPITAL) "CAPITAL", REEMPLAZAR(INTER) "INTERESES", CTA "CUENTA CONTABLE" FROM DOCUMENTOS; |
En la vista realizamos nuestros formatos, cálculos y demás cosas necesarias para dejarla lista para mostrar, los alias de las columnas las colocamos en comillas dobles y luego las usaremos como columnas para la tabla html. Esto limita lo que se puede hacer con dicha vista pero es perfecta para el reporte.
Luego en java para tomar la información de las columnas, hacemos uso del método del statement getMetaData(), supongamos que tengamos un DAO con un método que realiza un simple select a la vista:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public Vector buscarDoc(String idCliente) throws SQLException { conexion = getConnection(); Vector doc = new Vector(); PreparedStatement ps = null; ResultSet rs = null; try { String sqlDoc = "SELECT * FROM v_documentos WHERE id_cliente = ?"; ps = conexion.prepareStatement(sqlDoc); ps.setString(1, idCliente); rs = ps.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); Vector columnas = new Vector(); for (int i = 1; i <= columnCount; i++ ) { // Columnas inicia en 1 if (i != 1){ // Saltamos el primero que es el ID del cliente String name = rsmd.getColumnName(i); columnas.addElement(name); } } doc.addElement(columnas); while (rs.next()) { Vector items = new Vector(); for (int i = 0; i < columnas.size(); i++ ) { // Vector inicia en 0 String dato = rs.getString(columnas.get(i).toString()); items.addElement(dato); } doc.addElement(items); } } catch (Exception se) { se.printStackTrace(); } finally { closeJdbcObjects(conexion, ps, rs); } return doc; } |
- Primero recorremos el nombre en las columnas y lo agregamos a un vector «columnas».
- Segundo recorremos los datos a partir de la columna anterior y lo agregamos a otro vector «items».
- Ambos se agregan al vector principal «doc» y aunque no exista registros, siempre devolverá las columnas.
Toma en cuenta que nos saltamos la primera columna id_cliente, ya que es un dato que no quiero mostrar en el reporte, esto es lo único que controlamos desde la aplicación y nos limita a que no podemos elegir que otra columna no mostrar, si luego deseamos eliminar otra, simplemente se quita de la vista.
En el lado de la vista tenemos un JSP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<table border="0" width="80%" align="center"> <c:forEach var="docItems" items="${doc}" varStatus="iterador"> <c:if test = "${iterador.index == 0}"> <!-- Header --> <tr> <c:forEach var="item" items="${docItems}"> <th><c:out value="${item}"/></th> </c:forEach> </tr> </c:if> <c:if test="${iterador.index > 0}"> <!-- Body --> <tr> <c:forEach var="item" items="${docItems}"> <td><c:out value="${item}"/></td> </c:forEach> </tr> </c:if> </c:forEach> </table> |
Donde recorremos el vector con un simple foreach y tomando en cuenta que el primer registro son los nombres de las columnas de la tabla (HEADER) y el resto son los registros a mostrar (BODY).
Quedando de una forma dinámica y automatizada de la siguiente manera:
Esto funciona para simples datos a mostrar, tiene sus limitantes, como por ejemplo, no poder indicar estilos directamente en la vista, también que la vista solo funcionaría para ese reporte ya que las columnas están modificadas para tal y no sería ideal utilizarla para consultar en otros módulos.