17 de diciembre de 2015

Controlar dinámicamente los datos de un Grid

Artículo original: Controlling grid data dynamically
http://www.ml-consult.co.uk/foxst-20.htm
Autor: Mike Lewis
Traducido por: Ana María Bisbé York


¿Cómo le puede dar a sus usuarios mayor control sobre los contenidos de un Grid en Visual FoxPro?

Supongamos que desea crear un formulario como el que se muestra en la figura 1. Como ve, utiliza un Grid para mostrar los datos de una tabla Productos. Los usuarios pueden controlar el contenido del Grid de las siguientes formas:

  • Pueden limitar los registros a mostrar en el Grid según la categoría seleccionada.
  • Pueden escoger cuál de los dos campos  - el nombre en Inglés o el nombre original - es el que va a aparecer en la columna Description.
  • Pueden estipular el orden para el Grid.

Figura1: Tres formas para que el usuario controle el Grid

Luego de hacer estas selecciones, el usuario presiona el botón Refresh. Los datos del Grid cambian para refrescar según la selección del usuario.

Está claro, ¿verdad? Entonces, ¿cómo podemos crear este formulario?

Primeras ideas

La primera idea pudiera ser acceder al dato por medio de una vista local. Esto suena razonable, ya que usted puede modificar el contenido de una vista parametrizada. Se puede hacer en la cláusula WHERE de una vista, de esta forma:

WHERE Products.Category = ?lcCat

Aquí, lcCat es una variable que guarda la categoría escogida por el usuario. Si especifica entonces la vista como RecordSource del Grid, el dato se filtrará por la categoría requerida tantas veces como se invoque la vista. La llamada a la función REQUERY() va en el evento Click del botón Refresh del formulario.

Hasta aquí todo bien, en lo relativo a los filtros. Pero no es posible parametrizar los campos a mostrar en las columnas dadas ni el orden de la vista. Es posible recrear toda la vista programáticamente cada vez que el usuario presione el botón Refresh; pero esto no es una solución particularmente elegante. ¿Existe alguna forma más sencilla?

Intentar SQL SELECT

Utilizar una instrucción SQL SELECT para crear un cursor suena muy prometedor. Sin mucha dificultad, puede escribir un SELECT que represente las opciones de los usuarios, y que genera un cursor, que puede ser utilizado como el RecordSource del Grid.

Vamos a asumir que hemos configurado las siguientes variables:

  • lcCat contiene la categoría requerida.
  • llEnglish es .T. si el usuario escoge English como el lenguaje para la descripción del producto (en cuyo caso vamos a utilizar el campo eng_name como la segunda columna). Es .F. si el usuario desea verlo en el lenguaje original (para lo cual va a utilizar en su lugar el campo prod_name).
  • lcOrder contiene el número de la columna por la que se ordenará el dato (se almacena como cadena de caracteres).

El código en el botón Refresh puede tener este aspecto:

SELECT product_id,; 
  IIF(llEnglish,eng_name,prod_name) AS descript,;
  unit_price, in_stock ;
  FROM Products ;
  WHERE ALLTRIM(Category) = ALLTRIM(lcCat) ; 
  ORDER BY &lcOrder INTO CURSOR csrTemp
THISFORM.refresh

La instrucción SELECT envía el dato requerido al cursor, csrTemp. Este es el RecordSource para el Grid, entonces después que el formulario fue refrescado, el Grid  debe mostrar exactamente el dato que necesita el usuario. Problema solucionado.

No es tan sencillo

Desafortunadamente, no es tan sencillo. Si va a crear este formulario y ejecutarlo, el SELECT debía traer el dato correcto; pero el Grid aparecería como un rectángulo vacío. No se verían los datos.

La razón para este comportamiento no es difícil de ver. Siempre que utilice SELECT para crear un cursor de esta forma, Visual FoxPro destruye primero el cursor existente (si existe), luego, construye completamente uno nuevo. El Grid se desestabiliza con esto, ya que no desea perder el RecordSource, ni siquiera por un pequeño instante. Debido a que los controles dentro del Grid, están enlazados al cursor, destruyendo el cursor se destruyen los controles dentro del Grid, por eso se ve el rectángulo vacío.

Existirá alguna diferencia si utilizamos una tabla física en lugar de un cursor para la salida del SELECT? No, no habrá diferencia alguna.

La solución

Sin embargo, una vez que se entiende lo que ocurre, no es difícil idear una solución. El truco es crear un segundo cursor como el RecordSource, y mover los datos desde el primer cursor (aquel creado por el SELECT) al segundo cursor, el que el usuario desea actualizar en el Grid.

Vamos a colocar el siguiente código en el evento Load del formulario:

CREATE CURSOR csrProducts ; 
  ( product_id C(6), descript C(40), ;
  unit_price N(6,2), in_stock N(6) )

Esto va a crear un cursor, llamado crsProducts, con la misma estructura que el generado por SELECT. Establezca este cursor como RecordSource del Grid.

En el botón Refresh, mantenga el SELECT tal y como lo tenía antes; pero agregue algo de código para copiar el contenido del cursor generado por ese SELECT (csrTemp) en un cursor nuevo (csrProducts). El código entonces sería así:

SELECT product_id, ;
  IIF(llEnglish,eng_name,prod_name) AS descript,;
  unit_price, in_stock ;
  FROM Products ;
  WHERE ALLTRIM(Category) = ALLTRIM(lcCat) ; 
  ORDER BY &lcOrder INTO CURSOR csrTemp
SELECT csrProducts 
ZAP 
APPEND FROM DBF("csrTemp")
THISFORM.refresh

El efecto de esto es copiar los resultados del SELECT en csrProducts. Después que se ha refrescado el formulario, el dato se mostrará correctamente en el Grid.

Vea que no puede utilizar el comando COPY TO para transferir los datos a csrProducts, debido a que ese comando crea un archivo nuevo. En su lugar, necesita limpiar (ZAP) el contenido existente de csrProducts y agregar los datos nuevos. Observe además, el uso de la función DBF(). Esto es necesario debido a que el comando APPEND FROM puede solamente copiar datos desde una tabla física. DBF() devuelve la ruta y el nombre del archivo real que guarda el cursor.

Un detalle final al que debe prestar atención. Probablemente desee que el Grid muestre algún dato inicialmente cuando aparece el formulario por primera vez. Este dato debe basarse en los valores predeterminados para las tres selecciones del usuario. Para lograr esto, simplemente agregue código al Init del formulario para hacer el Select y para abrir los resultados en csrProducts. Por supuesto, va a necesitar además código para configurar las variables utilizadas en el SELECT (lcCat, llEnglish and lcOrder),  pero dejaremos esto como ejercicio para el lector.

Agradecimientos

La técnica que se ha descrito está basada en parte en la información del excelente libro "1001 Things You Always Wanted to Know About Visual FoxPro", por Marcia Akins, Andy Kramek y Rick Schummer (Hentzenwerke, 2000). Puede ver un resumen de este libro en nuestra página dedicada a libros: http://www.ml-consult.demon.co.uk/MLCBooks.htm o buscar más información en Amazon.com.

Mike Lewis Consultants Ltd. Septiembre 2001

No hay comentarios. :

Publicar un comentario