|
A veces nos hemos preguntado. ¿Y si fuera más fácil y más claro en ASP hacer un datagrid sin tener todos los códigos html y asp entremezclados? Qué gran injusticia sentimos cuando programamos en asp, y no podemos utilizar el control DataGrid de .Net!!! Qué desgracia para un purista ver todos esos comandos enredados y apelogotonados!!
No nos quejemos que los códigos están en nuestras manos para intentar crear la ilusión de que todo se automatiza más. Los controles de .Net no son más que clases y por lo tanto cualquier otro lenguaje puede imitarlo, aunque sin el soporte de la magnífica plataforma de Visual Studio.
He programado una clase que tiene bastantes posibilidades, aunque no la he perfeccionado, quería ofrecerla aquí al mundo internauta y si alguien tiene el tiempo y la paciencia de perfeccionarla. Please, make me know!!
Vamos a producir un Datagrid con esta clase que pagina cada 30 ítems y que va a mostrar hasta 20 números a los que navegar, que además mostrará enlaces de "inicio", "anterior", "siguiente" y "fin.
dim updateGrid
set updateGrid=new HtmlDatagrid
updateGrid.arConexion=arConexion
updateGrid.arCampos= Array("idcentro","nombre","direccion","codigopost","prov","telefono")
updateGrid.strOrder="nombre ASC"
updateGrid.arCamposVisible=Array(0,1,1,1,1,1)
updateGrid.arThCampos=Array("id","Nombre","Dirección","Código Postal","Provincia","Teléfono")
updateGrid.btnPaginar=1 'con esto hacemos que aparezcan los botones de inicio etc...
updateGrid.numPaginar=30
updateGrid.numerosPaginacion=20
updateGrid.TableAttr="cellSpacing=""1"" id=""itemstable"" cellPadding=""1"" width=""100%"" border=""0"" style=""margin-top:30px"" summary=""Resultados de búsqueda de centros, dividido en: nombre, dirección y teléfono""" 'estilos de las filas
updateGrid.arAttr= Array ("valign='top' align='center'","valign='top'","valign='top'","valign='top' align='center'","valign='top'","valign='top'") 'estilos de la cabecera
updateGrid.arThAttr=Array("class=""fondocolorlogoclaro"" width=""60"" align=""left""","class=""fondocolorlogoclaro"" width=""120"" align=""left""","class=""fondocolorlogoclaro"" width=""160"" align=""left""","class=""fondocolorlogoclaro"" width=""100"" align=""center""","class=""fondocolorlogoclaro"" width=""120"" align=""left""","class=""fondocolorlogoclaro"" width=""120"" align=""left""")
updateGrid.display()
Como se ve es bastante sencillo.
Pero bueno, estudiemos el abracadabra-pata-de-cabra del código.
1.-Creamos la instancia de la clase.
set updateGrid=new HtmlEditDatagrid
2.-Le asignamos la conexión que debe ser un array con 5 valores:
updateGrid.arConexion=arConexion
tal que así:
Dim arConexion(5) 'array de conexion arConexion(0)="SQLOLEDB" 'proveedor de base de datos arConexion(1)="servidor" 'direccion del servidor arConexion(2)="basededatos" 'base de daots arConexion(3)="usuario" arConexion(4)="contraseña" arConexion(5)="tabla"
3.-Definimos los campos que vamos a recoger de nuestra consulta a la base de datos en un array, y cómo queremos que aparezcan ordenados:
updateGrid.arCampos= Array("idcentro","nombre","direccion","codigopost","prov","telefono")
updateGrid.strOrder="nombre ASC"
4.- Le colocamos el nombre de cabecera que se nos antoje, pero queremos que no aparezca una columna que se llame id, así que con la propiedad arCamposVisible le asignamos un 0:
updateGrid.arThCampos=Array("id","Nombre","Dirección","Código Postal","Provincia","Teléfono")
updateGrid.arCamposVisible=Array(0,1,1,1,1,1)
5.-Ahora definimos cómo queremos paginar:
updateGrid.btnPaginar=1 'igualado a 1, incluimos hiperenlaces a inicio, anterior,siguiente…
updateGrid.numPaginar=30 'mostrar 30 ítems
updateGrid.numerosPaginacion=20 'mostrar hiperenlaces a 20 páginas
6.-Lo demás: updateGrid.TableAttr, updateGrid.arAttr, updateGrid.arThAttr sirve para definir los estilos de la tabla, de las filas y la cabecera etc…
7.-Finalmente lo mostramos:
updateGrid.display()
Para realizar esta maravilla os dejo la clase más abajo, pero aviso, no está nada pulida, pero cubre bastantes de las necesidades del día a día del programador.
Con esta clase he podido hacer también que las filas sean editables, sin tocar casi nada, también se pueden separar las celdas por celdas de imágenes que no tengan ninguna funcionalidad, se pueden agrupar campos y colocarlos en uno sólo, se puede crear un filtro en la consulta (where x like '%x%'), etc…
Ya iré mostrando otros ejemplos sobre el uso de esta clase en el futuro.
CLASE HTMLDATAGRID:
class HtmlDatagrid public arConexion public arCampos public arCamposVisible public arFilter public strAdicional public strOrder public TableAttr public arThcampos public arThAttr public arAttr public numPaginar public numerosPaginacion public separadorCells public btnCampos public classTr public btnPaginar
function display()
Response.Write(me.createDataGrid())
end function
function createDataGrid()
Dim conn1 'la conexión Dim rs1 'el recordset Dim strQuery 'cadena de la consulta Dim strCells 'el resultado devuelto: las celdas Dim arCamposLen 'longitud del array de campos Dim pagina_actual 'por si estamos paginando recupera el valor de página actual
on error resume next
arCamposLen=Ubound(arCampos)
set conn1=Server.CreateObject("ADODB.Connection") conn1.ConnectionString="Provider=" & arConexion(0) & ";Data Source=" & arConexion(1) & ";Initial Catalog=" &arConexion(2) & ";uid=" & arConexion(3) & ";PWD=" & arConexion(4) conn1.Open
'----------------[creación de recordset]---------------
set rs1=Server.CreateObject("ADODB.Recordset")
'ordenación por strOrder rs1.Sort=strOrder rs1.ActiveConnection=conn1 rs1.CursorType=1 rs1.LockType=3 rs1.CursorLocation=3
'-----------construimos cadena de la consulta Dim i 'dummy Dim campo 'dummy for i=0 to arCamposLen
'si el campo es un array 'puede ser un array porque es posible que queramos agrupar 'varios campos en una fila if isArray(arCampos(i)) then for each campo in arCampos(i) strQuery=strQuery & campo strQuery=strQuery & "," next else 'si el campo no es un array strQuery=strQuery & arCampos(i) strQuery=strQuery & ","
end if next 'le quitamos la última coma strQuery=left(strQuery,Len(strQuery)-1) '------------------[filtramos según arFilter]
if isArray(arFilter) then Dim strFilter Dim strSeparadorIni Dim strSeparadorFin
'nuestro filtro incluye 3 campos así que saltamos de 3 en 3 for i=0 to Ubound(arFilter) step 3
'aquí es donde vamos a utilizar un tipo de operador u otro if arFilter(i+1)="like" then
strSeparadorIni="'%" strSeparadorFin="%'"
else strSeparadorIni="'" strSeparadorFin="'" end if
strFilter=strFilter & arFilter(i) & " " & arFilter(i+1) & strSeparadorIni & arFilter(i+2) & strSeparadorFin & "and "
next
'le extraemos el último "and" strFilter=left(strFilter,Len(strFilter)-4) strFilter=" where " & strFilter end if
strQuery="select " & strAdicional & strQuery & " from " & arConexion(5) & strFilter
'Response.Write(strQuery)
rs1.Source=strQuery
rs1.Open
if not rs1.EOF then 'if -rs1.eof '--------recuperamos la página en la que nos encontramos en caso de estar paginando
Dim strResults ' recoge los números de la paginación etc... Dim numRegistros 'número de registros del recordset numRegistros=rs1.recordcount
'Response.Write(numRegistros)
if numPaginar<>"" and numRegistros>numPaginar then '--------if-paginacion
if (request.queryString("page") <> "") then pagina_actual = request.queryString("page") else pagina_actual = 1 end if
'si existe algún resultado, ejecuta el resto
rs1.pagesize=numPaginar rs1.absolutePage = pagina_actual 'nos situamos en la página actual
'---------creamos el índice de páginas
'resultados strResults=strResults & "<br>Resultados <b>" & (pagina_actual*numPaginar-numPaginar+1) & " a " & ((pagina_actual*numPaginar)) & "</b>" strResults=strResults & "<br><br>" strResults=strResults & "<center>" if pagina_actual <>1 then
'hacemos que aparezcan los botones de inicio etc... if btnPaginar<>"no" then strResults=strResults & "<a href=""?page=1"" class=""paginar"" title=""ir a inicio"">[Inicio]</a>" strResults=strResults & "<a title=""Ir a pagina anterior"" class=""paginar"" href=""?page=" & (pagina_actual-1) & """>[Anterior]</a>"
end if
end if
'números de paginación
dim k 'dummy dim hrefClass 'la clase de los números k=1
dim numDiv 'nos va a servir para corregir un error dim numPag numPag=0 'guarda número del menu de las páginas que se muestra Do While k <= rs1.PageCount
numDiv=roundDown(pagina_actual/numerosPaginacion)
if pagina_actual mod numerosPaginacion = 0 then
numDiv=numDiv-1
end if
numPag=numDiv*numerosPaginacion
numPag=numPag+k 'sólo vamos a mostrar numerosPaginacion páginas if k<=numerosPaginacion and numPag<=rs1.PageCount then
'sólo vamos a mostrar numerosPaginacion páginas if rs1.PageCount>numerosPaginacion then
if numPag=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a> </b>"
else
if k=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a> </b>"
end if k=k+1
else exit do end if
Loop
'insertamos letreros de siguiente y fin if cint(pagina_actual)<> rs1.PageCount then if btnPaginar<>"no" then strResults=strResults & "<a href=""?page="& (pagina_actual+1) & """ class=""paginar"" title=""ir a página siguiente"">[Siguiente]</a>" strResults=strResults & "<a title=""Ir a página final"" class=""paginar"" href=""?page=" & (rs1.PageCount) & """>[Fin]</a>" end if end if
strResults=strResults & "</center>" strCells=strCells & strResults
end if '-------if-paginacion
'-------------------[loop: creación de cabecera]-------------------
strCells=strCells & "<table " & TableAttr & ">" dim j 'dummy
if isArray(arThcampos) then'if-arthAttr
strCells=strcells & "<tr>" for j=0 to arCamposLen
if arCamposVisible(j)=1 then strCells=strCells & "<TH " & arThAttr(j) & "><b> " & arThcampos(j) & "</b> </TH>" end if next
strCells=strCells & "</tr>"
end if'if-arthAttr
'----------------[loop: creación de tabla]---------------
if numPaginar="" then 'colocamos la paginación más allá de cualquier límite si no existe numPaginar=100000 end if
Dim cuentaRegistros cuentaRegistros=0 'contaremos cuántos registros muestra para que pare en numPaginar
dim cellValue 'valor de los campos, de no haber, se sustituye por en caso de que utilicemos bordes es útil dim m 'dummy dim boton 'variable que utilizaremos si hay botones dim campovalor'tambien lo utilizamos si hubiera botones
if classTr<>"" then classTr="class=""" & classTr & """" end if
do while not rs1.EOF and cuentaRegistros<numPaginar
cuentaRegistros=cuentaRegistros+1 'esto hará que se pare en numPaginar
strCells=strCells & "<tr " & classTr & " >"
'creamos las celdas for j=0 to arCamposLen 'for-arcamposlen cellValue="" 'si queremos que se vea if arCamposVisible(j)=1 then 'if -visible 'si es una agrupación de valores if IsArray(arCampos(j)) then m=0 for each campo in arCampos(j) cellValue=cellValue & rs1(campo)& arGroupFSeparators(m) m=m+1 next 'si es botón es que el campo es "' ' as" 'si es un alias para crear botones etc... elseif left(arCampos(j),1)="'" then boton=btnCampos(j) campovalor=arCampos(j) campovalor=mid(campovalor,2,1) campovalor=arCampos(campovalor) campovalor=rs1(campovalor) execute("cellValue=" & boton & "(""" & campovalor & """)" ) else if rs1(arCampos(j))="" or rs1(arCampos(j))=" " or rs1(arCampos(j))=" " then cellValue=" " else cellValue=rs1(arCampos(j)) end if end if
strCells=strCells & "<TD " & arAttr(j) & ">"& cellValue & "</td>"
end if'if -visible next 'for-arcamposlen strCells=strCells & "</tr>"
'si hay un separador de celdas que hayamos pasados como parámetro
if separadorCells<>"" then
strCells=strCells & separadorCells
end if
rs1.MoveNext
loop
'cerramos tabla strCells=strCells & "</table>"
'------------paginación 2 if numPaginar<>"" and numRegistros>numPaginar then strCells=strCells & strResults end if
else 'if -rs1.eof
Response.Write ("<br>No se ha encontrado ningún registro<br>")
end if 'if -rs1.eof
'--------------[destrucción de objetos]---------------
rs1.Close set rs1=nothing
conn1.Close set conn1=nothing
if err<>0 then
Response.Write("<font color=red>Ha habido un error en la ejecución de esta página. Inténtelo de nuevo</font>") end if On Error GoTo 0
createDataGrid=strCells
end function
end class
class HtmlEditDatagrid public arConexion public arCampos public arCamposVisible public arFilter public strAdicional public strOrder public TableAttr public arThcampos public arThAttr public arAttr public numPaginar public numerosPaginacion public separadorCells public btnCampos public classTr public btnPaginar
function display()
Response.Write(me.createDataGrid())
end function
function createDataGrid()
Dim conn1 'la conexión Dim rs1 'el recordset Dim strQuery 'cadena de la consulta Dim strCells 'el resultado devuelto: las celdas Dim arCamposLen 'longitud del array de campos Dim pagina_actual 'por si estamos paginando recupera el valor de página actual
on error resume next
arCamposLen=Ubound(arCampos)
set conn1=Server.CreateObject("ADODB.Connection") conn1.ConnectionString="Provider=" & arConexion(0) & ";Data Source=" & arConexion(1) & ";Initial Catalog=" &arConexion(2) & ";uid=" & arConexion(3) & ";PWD=" & arConexion(4) conn1.Open
'----------------[creación de recordset]---------------
set rs1=Server.CreateObject("ADODB.Recordset")
'ordenación por strOrder rs1.Sort=strOrder rs1.ActiveConnection=conn1 rs1.CursorType=1 rs1.LockType=3 rs1.CursorLocation=3
'-----------construimos cadena de la consulta Dim i 'dummy Dim campo 'dummy for i=0 to arCamposLen
'si el campo es un array 'puede ser un array porque es posible que queramos agrupar 'varios campos en una fila if isArray(arCampos(i)) then for each campo in arCampos(i) strQuery=strQuery & campo strQuery=strQuery & "," next else 'si el campo no es un array strQuery=strQuery & arCampos(i) strQuery=strQuery & ","
end if next 'le quitamos la última coma strQuery=left(strQuery,Len(strQuery)-1) '------------------[filtramos según arFilter]
if isArray(arFilter) then Dim strFilter Dim strSeparadorIni Dim strSeparadorFin
'nuestro filtro incluye 3 campos así que saltamos de 3 en 3 for i=0 to Ubound(arFilter) step 3
'aquí es donde vamos a utilizar un tipo de operador u otro if arFilter(i+1)="like" then
strSeparadorIni="'%" strSeparadorFin="%'"
else strSeparadorIni="'" strSeparadorFin="'" end if
strFilter=strFilter & arFilter(i) & " " & arFilter(i+1) & strSeparadorIni & arFilter(i+2) & strSeparadorFin & "and "
next
'le extraemos el último "and" strFilter=left(strFilter,Len(strFilter)-4) strFilter=" where " & strFilter end if
strQuery="select " & strAdicional & strQuery & " from " & arConexion(5) & strFilter
'Response.Write(strQuery)
rs1.Source=strQuery
rs1.Open
if not rs1.EOF then 'if -rs1.eof '--------recuperamos la página en la que nos encontramos en caso de estar paginando
Dim strResults ' recoge los números de la paginación etc... Dim numRegistros 'número de registros del recordset numRegistros=rs1.recordcount
'Response.Write(numRegistros)
if numPaginar<>"" and numRegistros>numPaginar then '--------if-paginacion
if (request.queryString("page") <> "") then pagina_actual = request.queryString("page") else pagina_actual = 1 end if
'si existe algún resultado, ejecuta el resto
rs1.pagesize=numPaginar rs1.absolutePage = pagina_actual 'nos situamos en la página actual
'---------creamos el índice de páginas
'resultados strResults=strResults & "<br>Resultados <b>" & (pagina_actual*numPaginar-numPaginar+1) & " a " & ((pagina_actual*numPaginar)) & "</b>" strResults=strResults & "<br><br>" strResults=strResults & "<center>" if pagina_actual <>1 then
'hacemos que aparezcan los botones de inicio etc... if btnPaginar<>"no" then strResults=strResults & "<a href=""?page=1"" class=""paginar"" title=""ir a inicio"">[Inicio]</a>" strResults=strResults & "<a title=""Ir a pagina anterior"" class=""paginar"" href=""?page=" & (pagina_actual-1) & """>[Anterior]</a>"
end if
end if
'números de paginación
dim k 'dummy dim hrefClass 'la clase de los números k=1
dim numDiv 'nos va a servir para corregir un error dim numPag numPag=0 'guarda número del menu de las páginas que se muestra Do While k <= rs1.PageCount
numDiv=roundDown(pagina_actual/numerosPaginacion)
if pagina_actual mod numerosPaginacion = 0 then
numDiv=numDiv-1
end if
numPag=numDiv*numerosPaginacion
numPag=numPag+k 'sólo vamos a mostrar numerosPaginacion páginas if k<=numerosPaginacion and numPag<=rs1.PageCount then
'sólo vamos a mostrar numerosPaginacion páginas if rs1.PageCount>numerosPaginacion then
if numPag=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a> </b>"
else
if k=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a> </b>"
end if k=k+1
else exit do end if
Loop
'insertamos letreros de siguiente y fin if cint(pagina_actual)<> rs1.PageCount then if btnPaginar<>"no" then strResults=strResults & "<a href=""?page="& (pagina_actual+1) & """ class=""paginar"" title=""ir a página siguiente"">[Siguiente]</a>" strResults=strResults & "<a title=""Ir a página final"" class=""paginar"" href=""?page=" & (rs1.PageCount) & """>[Fin]</a>" end if end if
strResults=strResults & "</center>" strCells=strCells & strResults
end if '-------if-paginacion
'-------------------[loop: creación de cabecera]-------------------
strCells=strCells & "<table " & TableAttr & ">" dim j 'dummy
if isArray(arThcampos) then'if-arthAttr
strCells=strcells & "<tr>" for j=0 to arCamposLen
if arCamposVisible(j)=1 then strCells=strCells & "<TH " & arThAttr(j) & "><b> " & arThcampos(j) & "</b> </TH>" end if next
strCells=strCells & "</tr>"
end if'if-arthAttr
'----------------[loop: creación de tabla]---------------
if numPaginar="" then 'colocamos la paginación más allá de cualquier límite si no existe numPaginar=100000 end if
Dim cuentaRegistros cuentaRegistros=0 'contaremos cuántos registros muestra para que pare en numPaginar
dim cellValue 'valor de los campos, de no haber, se sustituye por en caso de que utilicemos bordes es útil dim m 'dummy dim boton 'variable que utilizaremos si hay botones dim campovalor'tambien lo utilizamos si hubiera botones
if classTr<>"" then classTr="class=""" & classTr & """" end if
do while not rs1.EOF and cuentaRegistros<numPaginar
cuentaRegistros=cuentaRegistros+1 'esto hará que se pare en numPaginar
strCells=strCells & "<tr " & classTr & " >"
'creamos las celdas for j=0 to arCamposLen 'for-arcamposlen cellValue="" 'si queremos que se vea if arCamposVisible(j)=1 then 'if -visible 'si es una agrupación de valores if IsArray(arCampos(j)) then m=0 for each campo in arCampos(j) cellValue=cellValue & rs1(campo)& arGroupFSeparators(m) m=m+1 next 'si es botón es que el campo es "' ' as" 'si es un alias para crear botones etc... elseif left(arCampos(j),1)="'" then boton=btnCampos(j)
|