FoxPress – Febrero 2004

 

Ordenación en Grid

http://www.fpress.com/

 

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:

Ordenar

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

GetIndiceColumna

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