Generador de listados con paginación

Se trata de un generador de listados de registros personalizado y con paginado.
Desde la página que queremos que contenga el listado simplemente tenemos que pasar la sentencia SQL, un array con los nombres de los campos que queremos que aparezcan como títulos (éstos deben coincidir con los de la sentencia SELECT en ese orden) y por último una llamada al método TableWizard pasandole la SELECT, el array de campos, el número de registros que queremos que aparezcan por página y, el último parámetro debería ser código en JavaScript que es lo que queremos que se ejecute cuando haga click en un registro en concreto (ésto último no está implementado por lo que si no modificáis el código tendréis que pasar "" en ese parámetro, pero os recomiendo que lo modifiquéis si necesitáis implementar esta funcionalidad).
Y con esas líneas más unas sencillas sentencias para la gestión de errores aparecerá una página con el resultado de la consulta y con posibilidad de paginación.

Consta de 4 ficheros para que pueda funcionar: La página .asp (LISTADO.ASP) en la que queremos que pinte el listado, la librería encargada de construir esa tabla de listado (TableWrapper.asp), la librería JavaScript que contiene un par de funciones, de momento, necesarias para el correcto funcionamiento de la paginación y del cambio de color del registro cuando pasamos el ratón por encima de él y, por último, el fichero BD.ASP que contiene todas las rutinas necesarias de base de datos para obtener la conexión y realizar la consulta.

Listado.asp

Debe incluir el fichero TableWrapper.asp (si no se encuentra en esa ruta lo modificáis)


<!--#include file="../lib/TableWrapper.asp"-->
<HTML>
<HEAD>
<title>Prueba de paginación empleando las librerías</title>
</HEAD>
<style>
H2 {font-family:verdana;}
HR {border:2px solid; color: black;}
</style>
<BODY>
<center>
<h2>Ejemplo de Paginación empleando las librerías</h2>
<hr>
<br><br>
<%
dim strSQLSelect
dim arrayNombresCampos
const REGISTROS_POR_PAGINA = 10 'Aquí ponéis los que queráis ver por página

on error resume next

strSQLSelect = "SELECT a_codigo,a_pais,a_telefono,a_email,a_texto FROM anuncios"
arrayNombresCampos = Array("Código","País","Teléfono","E-Mail","Descripción")
Call TableWizard (strSQLSelect, arrayNombresCampos, REGISTROS_POR_PAGINA, "", numError)
if numError <> 0 then
Response.Write "<br><b>ERROR: </B>" & numError
end if
%>
</center>
</BODY>
</html>


TABLEWRAPPER.ASP

Debe incluir el fichero BD.ASP (si no se encuentra en esa ruta lo modificáis), y necesita que hagáis referencia al fichero TableWrapper.js.
Este fichero tiene una serie de constantes de configuración donde podéis cambiar principalmente los colores, pero podéis crear otras nuevas siempre y cuando modifiquéis la estructura de la tabla que genera para que se haga referencia a esa nueva constante. Yo, por ejemplo, no he contemplado que la tabla tenga borde, pero si queréis dar esa opción configurable os tendréis que crear una constante con valor y luego hacer una pregunta que indique que si el valor de esa constante es, por ejemplo, "SI" pues que ponga 'border="1"'.

<!--#include file="../lib/bd.asp"-->
<% 'Página: TableWrapper.asp
'Autor: Ismael Zori Martínez
'Fecha: 1/5/2002
'FUM: 1/5/2002
'Comentarios: Esta página debe ser incluida desde la página de la
' consulta. Se puede ver el funcionamiento examinando
' la página "paginación.asp" dentro de la carpeta
' "pruebas".
' En principio no se debería modificar la función
' "TableWizard", simplemente se deberían cambiar los
' valores de las CONSTANTES DE CONFIGURACION.
'Requerimientos (ficheros requeridos):
' - TableWrapper.js
' - bd.asp

'CONSTANTES DE CONFIGURACION:
const FUENTE_FACE = "verdana, arial, helvetica"
'Contador:
const FUENTE_COLOR_CONT = "white"
const FUENTE_TAM_CONT = "8pt"
const COLOR_FONDO_CONT = "#123456"
const COLOR_BORDE_CONT = "#123456"
'Cabecera:
const FUENTE_COLOR_CAB = "white"
const FUENTE_TAM_CAB = "8pt"
const COLOR_FONDO_CAB = "#123456"
'Registro:
const FUENTE_COLOR_REG = "black"
const FUENTE_TAM_REG = "8pt"
const COLOR_FONDO_REG = "#aabbcc"
const COLOR_BORDE_LISTADO = "#123456"
const COLOR_ACTIVADO_REG = "aacccb"
const FUENTE_COLOR_ACTIVADO_REG = "#123456"
'A: (Enlaces de Primero, Anterior, Siguiente y Último)
const COLOR_LINK = "#aabbcc"
const COLOR_HOVER = "#aabbcc"
const COLOR_VISITED = "#aabbcc"
const COLOR_ACTIVE = "#aabbcc"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


'Función: TableWizard
'Autor: Ismael Zori
'Fecha: 1/5/2002
'Comentarios: Esta función es llamada desde la página ASP
' para construir una tabla de resultados paginados.
' Ver funcionamiento en página "paginación.asp" dentro
' de carpeta "pruebas".
'Parámetros: - strSQLSelect: Cadena SQL con la consulta.
' - arrayNombresCampos:
Array con los nombres de los campos asociados a cada campo devuelto por la consulta.
' Estos nombres son los nombres ficticios que ponemos a cada campo.
' Tienen que coincidir en número a los contenidos en la SELECT.
' - numRegPorPagina:
Número de registros que queremos visualizar por página (suele ser 10).
' - strOnClick: No implementado. Pero aquí es donde tendremos que poner el código JScript que queremos que se
' ejecute cuando pinchemos en un registro del listado.
' - numError: [ByRef]Aqui nos
'cargará el error en caso de existir uno durante el proceso. Si el valor es 0 no hay error.
Sub TableWizard (byval strSQLSelect, byval arrayNombresCampos,
byval numRegPorPagina, byval strOnClick, byref numError)
dim conConexion
dim rsConsulta
dim numPos
dim numInicio, numFin
dim numPagina

on error resume next
set rsConsulta = rsConsultar(strSQLSelect, conConexion, numError)
if numError <> 0 then
if not rsConsulta is nothing then
rsConsulta.close
set rsConsulta = nothing
end if
set conConexion = nothing
end if

'Posicionamos en la página indicada:
if Request("_hidPagina") = "" then
numPagina = 1
else
numPagina = CInt(Request("_hidPagina"))
end if

rsConsulta.PageSize = numRegPorPagina
Select case UCase(Request("_hidDireccion"))
case "FIRST"
numPagina = 1
case "PREVIOUS"
numPagina = numPagina - 1
case "NEXT"
numPagina = numPagina + 1
case "LAST"
numPagina = rsConsulta.PageCount
end select

rsConsulta.AbsolutePage = numPagina
numInicio = 1 + ((numPagina - 1) * numRegPorPagina)
numFin = numPagina * numRegPorPagina
if numFin > rsConsulta.RecordCount then
numFin = rsConsulta.RecordCount
end if
'Todo ha ido bien: (pintamos la tabla)
%>
<style>
.cont {font-family:<%=FUENTE_FACE%>;font-size:<%=FUENTE_TAM_CONT%>;color:<% =FUENTE_COLOR_CONT%>;background-color:<%=COLOR_FONDO_CONT%>;}
.cab {font-family:<%=FUENTE_FACE%>;font-size:<%=FUENTE_TAM_CAB%>;color:
<%=FUENTE_COLOR_CAB%>;
background-color:<%=COLOR_FONDO_CAB%>;font-weight:bold;}
.reg {font-family:<%=FUENTE_FACE%>;font-size:<%=FUENTE_TAM_REG%>;color:
<%=FUENTE_COLOR_REG%>;background-color:<%=COLOR_FONDO_REG%>;}
A:hover {text-decoration:underline;color:<%=COLOR_HOVER%>;}
A:visited {text-decoration:none;color:<%=COLOR_VISITED%>;}
A:link {text-decoration:none;color:<%=COLOR_LINK%>;}
A:active {text-decoration:none;color:<%=COLOR_ACTIVE%>;}
</style>
<script language="JavaScript"
src="http://<%=Request.ServerVariables("SERVER_NAME")%>
proyecto/lib/TableWrapper.js"></script>
<!-- esta ruta puede estar en una constante
en una variable application cargada en el
Global.asa o como se encuentra en este caso-->

<form name="_frmConsulta" method="post">
<input type="hidden" name="_hidPagina" value="<%=numPagina%>">
<input type="hidden" name="_hidDireccion" value="">
<table cellpadding="1" cellspacing="1" border="0" width="700" height="20"
style="border:1px solid <%=COLOR_BORDE_CONT%>;">
<tr class="cont">
<td width="150">
<% if rsConsulta.RecordCount <> 0 then %>
Del <%=numInicio%> al <%=numFin%>
<% else
Response.Write "Ningún registro"
end if %>
</td>
<td width="330"> </td>
<td align="right">
<a href="javascript:goPage('FIRST')">inicio</a>
<% if numPagina > 1 then %>
<a href="javascript:goPage('PREVIOUS');">anterior</a>
<% else %>
anterior
<% end if %>

<% if numPagina < rsConsulta.PageCount then %>
<a href="javascript:goPage('NEXT');">siguiente</a>
<% else %>
siguiente
<% end if %>

<a href="javascript:goPage('LAST');">fin</a>
</td>
</tr>
</table>
<br>
<table cellpadding="1" cellspacing="1" border="0" width="700" style="border:1px solid <%=COLOR_BORDE_LISTADO%>">
<tr class="cab">
<% for numPos = 0 to UBound(arrayNombresCampos) %>
<td align="center"><b><%=arrayNombresCampos(numPos)%></b></td>
<% next %>
</tr>
<% numConta = 0
while numConta < rsConsulta.PageSize and not rsConsulta.EOF %>
<tr class="reg" valign="top" onmouseover="colorReg(this,'
<%=COLOR_ACTIVADO_REG%>','<%=FUENTE_COLOR_ACTIVADO_REG%>')" onmouseout="colorReg(this,'<%=COLOR_FONDO_REG%>','<%=FUENTE_COLOR_REG%>')">
<% for numPos = 0 to UBound(arrayNombresCampos) %>
<td><%=rsConsulta(numPos)%></td>
<% next %>
</tr>
<% numConta = numConta + 1
rsConsulta.MoveNext
wend
%>
</table>
<br>
<table cellpadding="1"
cellspacing="1" border="0" width="700" height="20" style="border:1px solid <%=COLOR_BORDE_CONT%>;">
<tr class="cont">
<td width="150">
<% if rsConsulta.RecordCount <> 0 then %>
Del <%=numInicio%> al <%=numFin%>
<% else
Response.Write "Ningún registro"
end if %>
</td>
<td width="330"> </td>
<td align="right">
<a href="javascript:goPage('FIRST')">inicio</a>
<% if numPagina > 1 then %>
<a href="javascript:goPage('PREVIOUS');">anterior</a>
<% else %>
anterior
<% end if %>

<% if numPagina < rsConsulta.PageCount then %>
<a href="javascript:goPage('NEXT');">siguiente</a>
<% else %>
siguiente
<% end if %>

<a href="javascript:goPage('LAST');">fin</a>
</td>
</tr>
</table>
</form>
<% rsConsulta.close
set rsConsulta = nothing
set conConexion = nothing
end sub
%>


BD.ASP

Contiene las rutinas de base de datos típicas para hacer consultas.
Aquí especificáis el DSN (de ODBC) para vuestra base de datos y el timeout de la conexión.

<%
'CONSTANTES DE LA CONEXION:
const CONNECTION_STRING = "DSN=GALLEGOS"
const CONNECTION_TIMEOUT = 5
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Nombre: conOpenDatabase
'Autor: Ismael Zori
'FUM: 24/04/2002
'Objetivos: Abre la conexión y retorna un objeto Connection.
' Abre la base de datos empleando la cadena de conexión
' obtenida de CONNECTION_STRING (constante que se puede
' modificar al comienzo de esta página.
'Retorno: ByRef: Número de error (0:No error)
function conOpenDatabase (byref numError)
dim conConexion

on error resume next

set conConexion = Server.CreateObject ("ADODB.Connection")
with conConexion
.ConnectionString = CONNECTION_STRING
.ConnectionTimeout = CONNECTION_TIMEOUT
.Open
end with
numError = Err.number
set conOpenDatabase = conConexion
end function

'Nombre: rsQuery
'Autor: Ismael Zori
'FUM: 24/04/2002
'Objetivos: Realiza una consulta pasandole un objeto Connection.
' Esta función se puede emplear cuando queremos realizar
' varias acciones empleando la misma conexión. Pero
' si lo que queremos hacer es realizar una consulta simple
' emplearemos la función rsConsultar.
'Retorno: ByRef: Número de error (0:No error)
function rsQuery (byval strSQL, byref conConexion, byref numError)
dim rsConsulta

on error resume next

set rsConsulta = server.CreateObject ("ADODB.Recordset")
with rsConsulta
.CursorType = 3
.CursorLocation = 3
.LockType = 1
.ActiveConnection = conConexion
.Open strSQL
end with
numError = Err.number
set rsQuery = rsConsulta
end function

'Nombre: rsConsultar
'Autor: Ismael Zori
'FUM: 24/04/2002
'Objetivos: Instancia un objeto Connection y realiza la consulta
' indicada en strSQL.
'Retorno: ByRef: Conexión. Para poder cerrarla cuando terminemos
' ByRef: Número de error (0:No error)
function rsConsultar (byval strSQL, byRef conConexion, byRef numError)
dim rsConsulta

on error resume next

numError = 0
set conConexion = conOpenDatabase(numError)
if numError <> 0 then
set conConexion = nothing
exit function
end if

set rsConsulta = rsQuery (strSQL, conConexion, numError)
if numError <> 0 then
if not rsConsulta is nothing then
rsConsulta.close
set rsConsulta = nothing
end if
set conConexion = nothing
exit function
end if

'Todo ha ido bien:
set rsConsultar = rsConsulta
end function
%>


TABLEWRAPPER.JS

Contiene un par de funciones necesarias para el correcto funcionamiento de la paginación y el efecto de cambio de color cuando pasamos el ratón por encima de un registro.

function goPage(strDireccion)
{
document._frmConsulta._hidDireccion.value = strDireccion;
document._frmConsulta.action = document.location.pathname;
document._frmConsulta.submit();
}

function colorReg (objTR, strColorFondo, strColorFuente)
{
objTR.style.backgroundColor = strColorFondo;
objTR.style.color = strColorFuente;
}

Una vez hecho esto sólo hay que probar a ejecutar el fichero LISTADO.ASP y si habéis copiado todo correctamente debería funcionar.
Puede que en principio sea un poco engorroso pero si necesitamos hacer muchas páginas con listado paginado simplemente tendremos que copiar y modificar la página LISTADO.ASP y, si las páginas son muy parecidas hasta podéis emplear la misma página para sacar todos los listados metiendo las instrucciones necesarias.

Puedes bajarte los módulos comprimidos en .zip pulsando AQUI

Compartir

Comentarios

Ramiro

06/11/2007
El articulo está excelente, pero existe lo mismo para usar en PHP. Mi server solo fucniona con PHP.
Gracias

Carlos Gómez Núñez

13/11/2007
Buen ejemplo, hace un tiempo ya hice algo parecido para aplicarlo en una de mis aplicaciones desarrolladas para la empresa en la que trabajo, es muy útil tener una función para hacer cosas de este estilo. Lo mismo hice con otro listado paginado que contiene el indicador del número de página a visitar el típico "<< 1, 2, 3... >>"
Y como este ejmplo estaba muy bien estructurado, me he "animado" y le he añadido alguna "cosilla" más, como por ejemplo, al pulsar sobre la cabecera de uno de los campos del listado lo ordeno "ascendientemente", si se pulsa otra vez lo ordena "descendientemente" con respecto al campo que se pulse, y así sucesivamente. Además le he añadido un combo para que me muestre varios niveles de número de registros a mostrar y lo bueno es que la velocidad de búsqueda sigue siendo prácticamente la misma. Los campos de fecha los necesitaba en horario de 24 Horas, y también lo he aplicado
La verdad es que da para mucho más, por eso gracias de nuevo...