Ordenación en Grid
Por Angel Casas Polo OrdenaGrid.zip
En ocasiones nuestros clientes desean
que las aplicaciones que desarrollemos cuenten con funcionalidades propias de las
herramientas comerciales que están acostumbrados a manejar con mayor asiduidad.
Dentro de este proceso de estandarización al que debemos someter a
nuestras aplicaciones, una de las mejoras más solicitadas es la que permite
ordenar los registros de un grid pinchando sobre la cabecera al estilo de
Microsoft Excel.
En este artículo veremos como podemos
desarrollar esto en nuestras clases de una forma sencilla y que nos permitirá
dotar a nuestras aplicaciones de esta funcionalidad con muy poco esfuerzo.
Comezaremos el ejemplo creando una tabla EMPLEADOS
con la siguiente estructura:
Como podemos observar no tiene creado ningún índice;
esto es indiferente para nuestros propósitos ya que la clase que diseñaremos
trabaja sobre un cursor y crea automáticamente los índices necesarios para su
funcionamiento.
A continuación diseñaremos una clase Header que será
la que substituya a la estándar del grid y nos permitirá realizar los procesos
de ordenación
DEFINE CLASS HeadOrden AS Header
Alignment =
2
FontSize = 8
Orden = ''
Procedure
Init
Lparameters pCampo, pIndiceCol
Local
cIndiceAsc, cIndiceDes
This.BackColor = Rgb(255, 255, 200)
This.ForeColor = Rgb(0, 64, 128)
cIndiceAsc = 'Index On ' + pCampo + ' Tag Clave' +
Alltrim(Str(pIndiceCol)) +
'Additive'
&cIndiceAsc
cIndiceDes = 'Index On ' + pCampo + ' Tag Clave' +
Alltrim(Str(pIndiceCol)) +
'd Descending Additive'
&cIndiceDes
This.Orden = Alltrim(Str(pIndiceCol))
EndProc
Procedure
Click
Local
Ejecutar
If
!CursorVacio(This.Parent.Parent.RecordSource)
If
Type('This.Parent.Parent.Header') == 'O' And
!Isnull(This.Parent.Parent.Header)
This.Parent.Parent.Header.BackColor =
Rgb(255, 255, 200)
EndIf
Ejecutar = 'Set Order To Clave' + This.Orden
+ ' In ' +
This.Parent.Parent.RecordSource
&Ejecutar
This.Parent.Parent.Header = This
This.BackColor = Rgb(181, 211, 171)
Go Top In (This.Parent.Parent.RecordSource)
This.Parent.Parent.Refresh()
Endif
Endproc
Procedure
RightClick
Local
Ejecutar
If
!CursorVacio(This.Parent.Parent.RecordSource)
If
Type('This.Parent.Parent.Header') == 'O' And
!Isnull(This.Parent.Parent.Header)
This.Parent.Parent.Header.BackColor
= Rgb(255, 255, 200)
EndIf
Ejecutar = 'Set Order To Clave' + This.Orden + 'd In ' +
This.Parent.Parent.RecordSource
&Ejecutar
This.Parent.Parent.Header = This
This.BackColor = Rgb(222, 164, 160)
Go Top In (This.Parent.Parent.RecordSource)
This.Parent.Parent.Refresh()
Endif
Endproc
Enddefine
** Función que devuelve
.t. cuando el cursor cCursor está vacío
Function CursorVacio
Lparameters cCursor
Local lEstaVacio
Go Top In
&cCursor
lEstaVacio
= Iif(Eof(cCursor), .t., .f.)
Return lEstaVacio
El código es realmente sencillo, en lnit del
Header se establecen los colores que tendrá una cabecera que permita la
ordenación y se crean los índices (ascendente y descendente) de la columna a
partir de la expresión pCampo que se pasa por parámetro y que
posteriormente veremos de donde proviene.
En el evento Click del Header, establecemos
como índice activo el de la ordenación ascendente y en el RightClick el
de la descendente. En ambos casos el proceso que se realiza es el siguiente
1)
Comprueba si hay datos
en el cursor que intentamos ordenar
2)
Comprueba que existe la
propiedad Header. Esta propiedad deberá ser creada por nosotros en la clase
Grid, que explicaremos posteriormente, y que sirve para restaurar los colores
cuando seleccionemos otra columna
3)
Restaura el color
original de la columna almacenada en la propiedad Header (o sea la columna con
la ordenación anterior)
4)
Guarda la columna
actual en la propiedad Header
5)
Establece el índice
6)
Establece un color
distinto para la cabecera que marca actualmente la ordenación
Tan solo nos queda definir una clase Grid llamada
grdOrden que contendrá la propiedad Header (que guarda la columna con la
ordenación activa) y los métodos:
Lparameters pColumna,
pCampo
Local cCaption
cCaption = pColumna.Header1.Caption
pColumna.RemoveObject('Header1')
pColumna.AddObject('grdHeader', 'HeadOrden', pCampo,
This.GetIndiceColumna(pColumna.Name))
pColumna.grdHeader.Caption = cCaption
Parameters pNombre
Local nI, nInd
nInd = 0
For nI = 1 To This.ColumnCount
If
Alltrim(Upper(pNombre)) == Alltrim(Upper(This.Columns[nI].Name))
nInd = nI
Exit
EndIf
Endfor
Return nInd
Situamos nuestro Grid en el formulario y en el Init
del mismo introducimos el código:
ThisForm.GrdOrden1.RecordSource = ''
Select * ;
From
Empleados ;
Into
Cursor cEmpleados ReadWrite
With ThisForm.GrdOrden1
.RecordSource
= 'cEmpleados'
.Column1.ControlSource
= 'cEmpleados.Codigo'
.Column2.ControlSource = 'cEmpleados.Nombre'
.Ordenar(.Column1, 'Codigo')
.Ordenar(.Column2, 'Nombre')
EndWith
Como podemos ver, una vez que tengamos creadas las
clases en nuestra librería, el incluir una cabecera que permita la ordenación
tanto ascendente como descendente, implica simplemente el incluir en nuestro
código las líneas:
ThisForm.grdOrden.Ordenar(.Column1, 'Codigo')
ThisForm.grdOrden.Ordenar(.Column2,
'Nombre')
Cuyos parámetros definen la columna del Grid que permitirá ordenación y la expresión del índice la cual puede ser compuesta, es decir, podríamos incluir lo siguiente:
ThisForm.grdOrden.Ordenar(.Column2,
'Codigo+Nombre')
FoxPress – Febrero de 2004