ASP


Dolor de cabeza: redondeando en ASP

Aquellos que hayáis programado en cualquier lenguaje medianamente aceptable,
habrá podido apreciar que las funciones matemáticas math.floor y math.ceil o
math.ceiling nos proporcionan métodos para redondear hacia abajo o hacia
arriba, cosa que para algunos casos es vital.
Pues bien, ASP ni lo huele.
No obstante, siempre podemos crearnos unos métodos ingeniosos para conseguir casi los mismos
resultados.

He creado 2 funciones que podemos llamar según queramos redondear hacia arriba
o hacia abajo, llamadas roundDown y roundUp, y después una función con piloto
automático y que decidirá si usar uno u otro método dependiendo de su decimal:
autoRound.

La gran pregunta aquí es qué pasa si le paso 10,5, pues según ocurre por ejemplo en
.NET se redondea hacia abajo, pero si está por encima, p.e., 10,51 se redondea hacia
arriba.
En un principio me plantee que examinaría el 2 decimal y si éste era mayor de 0 redondearía
hacia arriba, pero que pasa si el número fuera 10,501. Con este método hubiera
redondeado hacia abajo, y shlaf!! gran error, gran horror.
Es por eso que en autoRound empleo un loop que me indicará si uno de los decimales
a partir del segundo decimal es mayor de 0 pues se redondeará hacia arriba.

Esta función también lo toma en cuenta:


Function roundDown(dblValue)
Dim myDec

myDec = InStr(1, CStr(dblValue), ",")
If myDec > 0 Then
    roundDown = CDbl(Left(CStr(dblValue), myDec))
Else
    roundDown = dblValue
End If

End Function

Function roundUp(dblValue)
Dim myDec

myDec = InStr(1, CStr(dblValue), ",")
If myDec > 0 Then
    roundUp = CDbl(Left(CStr(dblValue), myDec)) + 1
Else
    roundUp = dblValue
End If

End Function

function autoRound(dblValue)
Dim myDec,pos,ini,aux

ini=1
pos = InStr(1, CStr(dblValue), ",")
myDec=left(mid(cstr(dblValue),pos+ini),1)
aux=false

If myDec > 5 Then
        autoRound = roundUp(dblValue)
       
    Else
   
    if myDec = 5 then   
   
            do while Len(myDec)>0 and aux=false and ini<100
                ini=ini+1
                myDec=left(mid(cstr(dblValue),pos+ini),1)       
                if not isNumeric(myDec) then myDec=0       
                if myDec>0 then               
                     aux=true
                end if
               
            loop
       
            if aux=true then
       
                 autoRound = roundUp(dblValue)
       
            else
       
                autoRound = roundDown(dblValue)
               
            end if
       
    else
   
            autoRound = roundDown(dblValue)
   
    end if
   
end if


end function

Response.Write "<br>"
Response.Write "10,66: " & autoRound("10,66") & "<br>"'El output será 11.
Response.Write "10,1: " &autoRound("10,1") & "<br>"'El output será 10.
Response.Write "10,55: " &autoRound("10,55") & "<br>"'El output será 11.
Response.Write "10,5555: " &autoRound("10,5555") & "<br>"'El output será 11.
Response.Write "10,5: " &autoRound("10,5") & "<br>"'El output será 10.
Response.Write "10,51: " &autoRound("10,51") & "<br>"'El output será 10.
Response.Write "10,501: " &autoRound("10,501") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10.
Response.Write "10,5001: " &autoRound("10,5001") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10.
Response.Write "10,5000: " &autoRound("10,5000") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10.
Response.Write "10: " &autoRound("10") & "<br>"'El output será 10.
 

Dejadme salir!!!

Para los que procedáis de PHP como yo mismo, le habréis dado algunas vueltas antes de encontrar el equivalente a Exit en ASP.
Cómo que no funciona la famosa etiqueta? Cuál será la solución? Antes de que empecemos a sudar, la solución es simplemente:
Response.End

Utilizar chr en lugar de caracteres

Como regla general, recomiendo utilizar chr para las sustituciones de tipo replace para
los caracteres especiales, por ejemplo, si quiero sustituir unas comillas,
pensemos en el siguiente código:

dim strPrueba

strPrueba="texto ""de prueba"""

strPrueba=replace(strPrueba,"""","")

No queda claro porque hay un barullo de dobles comillas propio de un lenguaje
como asp.

En su lugar yo utilizaría algo más elegante:
strPrueba=replace(strPrueba,chr(34),"")

Podemos buscarle utilidades interesantes al método chr, el más útil diría yo que es
el carácter que indica retorno de carro.
Esto es útil cuando el texto ha sido insertado desde un textarea. Se trata del carácter 13, el 13 es tu número como
dicen en las pelis americanas.
Con el siguiente source podrás convertir esos caracteres a saltos de html.

textArticle= replace(strPrueba, chr(13),"<br>")

Otra utilidad muy interesante es sustituir barras inclinadas hacia un lado por otras hacia el otro lado.

Otro truco al respecto, podéis saber a qué corresponde cada caracter así:

for i=0 to numMax step 1

Response.Write (i & ":" & chr(i) & "<br>")

next

Función/método para combatir el SQL INJECTION

Como no podía faltar, os presento aquí una función que os será utilísima para aquellos que pasáis de procedimientos almacenados o que no os viene bien o no podéis o... bueno, paro ahí.

Se trata de una función o método para combartir el SQL INJECTION. Como todos sabéis, es un ataque a través de la barra de navegación o a través de cajas de texto en vuestra web etc... en el que se inyectan códigos malignos tipo DELETE etc... para dañar vuestra web o simplemente para acceder a sitios restringidos.

Bueno sin enrollarme más y agradeciendo la refinación de la función a mi compañero Andrés os dejo aquí esta función que deberíais incluir en vuestra librería de utilidades:

Function AntiSqlInjection(cadena)

dim charReplace, valuesBanned, x

'constantes de caracteres a eliminar

Const CHARS = "'%/\<>()"

 

For x = 1 To Len(CHARS)

            charReplace = MID(CHARS, x, 1)

            cadena = Replace(cadena, charReplace, " ")

Next

 

'no queremos estos valores prohibidos

valuesBanned=Array("select","delete","update","insert", "truncate", "drop", "--")

for each valuesBanned in valuesBanned

            cadena=Replace(lcase(cadena),valuesBanned,"")

next

AntiSqlInjection=cadena

End Function

Clase para creación automática de Datagrids

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 & "&nbsp;<b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a>&nbsp;</b>"

else

if k=cint(pagina_actual)   then
hrefClass="negrita"
else
hrefClass="paginarN"
end if

strResults=strResults & "&nbsp;<b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a>&nbsp;</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 &nbsp; 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="&nbsp"
                    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 & "&nbsp;<b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a>&nbsp;</b>"

else

if k=cint(pagina_actual)   then
hrefClass="negrita"
else
hrefClass="paginarN"
end if

strResults=strResults & "&nbsp;<b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a>&nbsp;</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 &nbsp; 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)