Anda di halaman 1dari 6

Trabajando con Grids, ZAP y PACK, porque no se llevan?

Enviado por esparta en Jueves, 25 Enero, 2007

lecturas 8253

En respuesta a la tipica pregunta: Cuando hago un ZAP o PACK a la tabla base de mi grid, ste "se blanquea", Porqu? El control Grid es un objeto muy poderoso dentro de los controles que maneja internamente Visual FoxPro, una evolucin lgica al comando Browse y al tan usado T-Browse de Clipper (casi no lo us pero me cuentan maravillas de l). El Grid nos permite ver la informacin de nuestra(s) tabla(s) de manera coherente, muy semejante a una hoja de clculo, pero a la vez muy flexible, ya que no solo nos permite mostrar la informacin de una tabla, sino que podemos relacionarla con otras y usar sus campos relacionados para mostrarlos. Un problema tpico que nos encontramos es con el uso de los comandos ZAP y/o PACK, ya que si intentamos ejecutarlos sobre la tabla base de nuestro Grid, este se "blanquea"... y con justa razn; Visual FoxPro utiliza una referencia directa a la estructura y los datos de esa tabla, cuando hacemos un ZAP o PACK, la referencia se destruye y es cuando las filas y columnas dejan de visualizarse. Entonces, que puedo hacer al respecto? Si lo que haces es solo mostrar la tabla, en determinado momento borrar registros, entonces no uses PACK, ya que este comando hace un borrado fsico de los datos, mismos que no debera ser parte de la ejecucin "normal" de tu aplicacin (1), si estas borrando registros y deseas que tu usuario no los vea, entonces simplemente haz que no se muestren, esto es por medio del comando SET DELETE ON. Existen casos especiales en que si usas Sesiones Privadas de Datos (Private Data Session) en tus Formularios, entonces muchas configuraciones toman su valor por defecto, en el caso de SET DELETED, este vuelve a un estado OFF, por lo que tendras que reconfigurarlo a ON en algun punto de la carga de tu formulario con sesin privada de datos; aqu es dnde conviene tener una clase base de los formularios, en donde por ejemplo, tengas en el evento LOAD la carga de todas las configuraciones necesarias (incluidas el SET DELETED) y crear tus formularios a partir de esta clase modificada (sub-clasear le llaman algunos). El usar SET DELETED ON ayudar a que tu aplicacin no dependa del uso exclusivo de tus archivos (requisito para usar PACK), con la consecuencia que ser bastante fcil adaptarla para ejecutarse en mltiples puestos (una aplicacin multiusuarios). Y que pasa con el comando ZAP? Muy poca gente quiere usar el comando ZAP, ya que como sabemos borra toda la

informacin de un cursor o tabla de VFP, pero a veces, segn sea necesario tendras que utilizarlo, en lo personal procuro no hacerlo y tampoco le veo mucho caso, y estos son algunos motivos:

Uso el comando ZAP nicamente para borrar el contenido de las tablas que van a ser distribuidas con la aplicacin. Si borro todos los datos de un cursor de VFP, es slo sobre cursores locales (creado con CREATE CURSOR, por ejemplo), no sobre tablas que podran ser usadas en mltiples estaciones. Como en el caso de PACK, mis usuarios no ven que borr todos los registros. A veces, en vez de borrar simplemente recreo el cursor.

Pero como dije, siempre habr casos especiales (o formas de programar). Muchos hemos aprendido que si hace una referencia directa al cursor base, entonces pues simplemente quitamos dicha referencia, hacemos el ZAP (o PACK) y regresamos la referencia. Sencillo, no?
*** Guardar el contenido de la propiedad RecordSource y limpiarla WITH ThisForm.Grid lcBoundTo = .RecordSource .RecordSource = '' *** Ejecutar el proceso con ZAP y/o PACK .RecordSource = lcBoundTo ENDWITH

Pues si, si funciona, es una buena idea al principio, muesta todos los datos... pero no una solucin completa, como dira Marcia Atkins, una de las tantas formas de darse un balazo en el pi. Si funciona, porqu buscarle mas? Algo que a veces no vemos (por prisas, o porque simplemente se cumple nuestro objetivo primario) es que podramos querer utilizar nuestros Grids de otras formas, y una de ella es programando sus eventos, tales como el DobleClick en un textbox o en el Header (2) , si programas algo parecido en el cdigo mostrado anteriormente, las referencias a los eventos que pre-programaste tambin se perdern! Una vez ms, Entonces qu hago? Existen una forma de hacerlo, y que no cuesta mucho trabajo implementarla, aunque si un cambio medio radical a nuestra metodologa, esto es nunca mover la referencia a nuestro cursor base, no voy a ahondar ms en el tema, ya que Andy Kramek ya ha escrito un excelente documento al respecto: --- Using a Safe Select to preserve your grid --http://weblogs.foxite.com/andykramek/archive/2005/03/19/174.aspx

Y nuestra amiga Ana Mara Bisb tuvo la amabilidad de traducirlo: --- Utilizar un Select seguro para preservar los grids --http://www.portalfox.com/modules.php?op=modload&name=Sections&file=index&req=vi ewarticle&artid=69 En los artculos anteriores se centra en cuestiones sobre realizar SELECTs, pero por supuesto es aplicable cualquier otro proceso que incluya el cerra el cursor (que es nuestro problema en el uso de los grids), ya se explcita o implcitamente. Como resumen tenemos dos casos, evitar el uso de PACK (con DELETE o DELETE-SQL + SET DELETED ON es suficiente), y cuando necesites ejecutar ZAP, hazlo de manera que no tengas inconvenientes en futuras ocasiones. Espero que este pequeo resumen les sea de utilidad. (1) El comando PACK cuando se aplica a tablas (lase DBF) debera ser utilizado nicamente para mantenimiento de las mismas, bajo un esquema de no uso, de manera peridica dependiendo del uso que se les d. (2) Esto tambin afecta cuando agregas controles a un Grid, un problema ms. -------------------------------

Utilizar un Select seguro para preservar los grids


(1073 palabras totales en este texto) (13550 lecturas)

Utilizar un Select seguro para preservar los grids


Artculo original: Using a Safe Select to preserve your grid (http://weblogs.foxite.com/andykramek/archive/2005/03/19/174.aspx) Autor:Andy Kramek (http://www.tightlinecomputers.com) Traducido por: Ana Mara Bisb York (amby@telefonica.net) Para: PortalFox (http://www.portalfox.com)

Un problema comn al trabajar con cursores locales en VFP es que cuando ellos se utilizan como origen para controles Grid, la recreacin del cursor provoca que el grid pierda parte o toda su configuracin. La razn por la que esto ocurre es que cada vez que se ejecuta una

sentencia SQL en VFP, el cursor destino existente se cierra, se elimina y se recrea. Como consecuencia, los datos del cursor se pierden y el grid pierde su enlace. Esto es fcilmente demostrable, considerando lo siguiente:
*** Ejecutar un select bsico a un cursor SELECT * FROM account INTO CURSOR JUNK NOFILTER ? DBF('junk') && Returns F:\TEMP\00002PL5008K.TMP *** Repetir la consulta SELECT * FROM account INTO CURSOR JUNK NOFILTER ? DBF('junk') && Returns F:\TEMP\00002PL500AQ.TMP

Como puede ver, la segunda ejecucin de la consulta crea un cursor nuevo que se abre con el mismo alias que el primero. Una comprobacin rpida al disco mostrar que el primer cursor ha sido efectivamente eliminado. La consecuencia para el grid es que tiene que reconstruirse por si mismo desde el principio. Entonces, elimina todas las columnas existentes y crea nuevas columnas para el nuevo origen de datos. El resultado es, por supuesto, que todas las configuraciones especficas de las columnas se pierden y si el grid emplea columnas personalizadas o los controles han sido reemplazados por clases propias (o, desde la introduccin de las clases member, en cualquier lugar que exista una clase member.) Por tanto, cualquier configuracin especfica se pierde y tiene que ser re-creada. Esto, no es bueno! Una solucin al problema, que ofrezco con frecuencia en los foros on-line, es establecer la propiedad RecordSource del grid a una cadena vaca antes de hacer la consulta y resturarlo luego de realizada, algo as:
*** Guardar el contenido de la propiedad RecordSource y limpiarla WITH ThisForm.Grid lcBoundTo = .RecordSource .RecordSource = '' *** Ejecutar la nueva consulta SELECT <fields> FROM <table> INTO CURSOR <recordsource> .RecordSource = lcBoundTo ENDWITH

y esto trabaja bien, permitiendo que el grid muestre las columnas en el orden natural. La razn para esta salvedad es que lo que ocurre en realidad en este caso es que al limpiar la propiedad RecordSource del grid, se limpia tambin la propiedad ControlSource para cada columna. Cuando el grid es re-enlazado a un alias nuevo no tiene especificado el ControlSource de cada columna y el resultado es que el grid muestra ahora los datos basados en la posicin del RecordSource. La primera columna muestra la primera columna del origen de datos, la segunda columna muestra la 2da y as sucesivamente. Generalmente lo que sucede a continuacin es que la persona que ha preguntado, trata la solucin ofrecida, encuentra que su grid est completamente revuelto y regresa al foro preguntando y ahora que hago? El siguiente paso suele ser sugerirle que cambie

enteramente su metodologa y que sustituya el cursor por una vista parametrizada. Esto es perfectamente vlido y una vista parametrizada trabajar muy bien para estos casos. Sin embargo, las vistas parametrizadas tienen una seria limitacin. Debido a que las vistas deben estar pre-definidas, no es fcil crear una vista que acepte una condicin de filtro para un propsito especfico y es precisamente este requerimiento el que lleva a los desarrolladores a emplear, en primer lugar, un cursor. Por ejemplo, en una pantalla de registro de clientes el requerimiento es permitir al usuario que especifique cualquier combinacin de First Name, LastName, Social Security Number, City, State, Order Number. Construir una vista parametrizada para controlarlo sera difcil, sino imposible. Una solucin para este problema es la tcnica conocida como "select seguro". La idea, es que debido a que los cursores se crean siempre en la estacin de trabajo local del usuario, y se abren siempre en exclusivo, podemos utilizar el comando ZAP para limpiar, sin cerrar, un cursor. Entonces, en lugar de correr una consulta directamente sobre un cursor de trabajo emplearemos un cursor intermedio (o "fantasma") como destino para la consulta y agregamos simplemente el resultado al cursor de trabajo. He aqu el cdigo para el "select seguro".
*** Crear un cursor de trabajo SELECT * FROM account WHERE 0 = 1 INTO CURSOR curacct READWRITE *** Ahora ejecutar la consulta real SELECT * FROM account WHERE name LIKE 'Sm%' INTO CURSOR curdummy *** Limpiar el cursor de trabajo y agregar el resultado. SELECT curacct ZAP IN curacct APPEND FROM DBF('curdummy') USE IN curDummy

Debido a que el cursor de trabajo no se cierra nunca, no hay ningn efecto sobre ningn control (incluyendo grids) que utilice el cursor como origen de datos. Esta tcnica nos permite mantener la flexibilidad de un cursor sin los efectos secundarios indeseados causados por las repetidas aperturas y cierres de las re-consultas. Por supuesto, si tiene que escribir este cdigo cada vez que desea re-crear un cursor podra ser bastante tedioso; pero tenemos un entorno completamente orientado a objeto en VFP, porqu no agregar un mtodo a su formulario base que acepte dos parmetros - la cadena para la consulta y el nombre del cursor destino. Entonces, el cdigo queda bien encapsulado y est disponible en cualquier forma que lo necesitemos. Puede incluso completar el cdigo de tal forma que si el cursor destino no existe, sea creado por este mtodo. He aqu mi mtodo base "SaveSelect" con el que espero recibir una cadena de consulta que NO incluya una clusula INTO - esto se agrega aqu:
LPARAMETERS tcSql, tcAlias LOCAL lnSelect, lcSql *** Guardar el rea de trabajo lnSelect = SELECT(0) *** No existe el cursor IF NOT USED( tcAlias )

*** Crearlo directamente lcSql = tcSql + " INTO CURSOR " + tcAlias + " READWRITE" &lcSql ELSE *** El cursor existe, utilizo un select seguro lcSql = tcSql + " INTO CURSOR curdummy" &lcSql *** Limpiar y actualizar el cursor de trabajo SELECT (tcAlias) ZAP IN (tcAlias) APPEND FROM DBF('curdummy') USE IN curdummy ENDIF *** Restablecer el rea de trabajo y devolver el estado SELECT (lnSelect) RETURN USED(tcAlias)

Y sobre la clusula READWRITE, si aun est utilizando una versin que no la soporte, existe una forma para hacerlo; pero no lo dir porque se debe haber Actualizado. No hay ninguna razn para no haberlo hecho y s muchsimas por las que debera - la principal es animar a Microsoft para que contine desarrollando VFP, por ejemplo ...

Anda mungkin juga menyukai