4 de diciembre de 2021

TRY ... CATCH ... FINNALY

A partir de Visual FoxPro 8 existe una nueva estructura de control TRY...CATCH...FINALLY para capturar errores o excepciones que ocurren en tiempo de ejecución.

La estructura TRY...CATCH...FINALLY comienza con una cláusula TRY que marca el inicio de un bloque TRY. En este bloque se puede especificar un grupo de cláusulas que pueden producir un error en tiempo de ejecucion. Si el programa completa el bloque TRY sin generar ninguna excepción, este salta el bloque CATCH y busca el bloque FINALLY y ejecuta las sentencias de ese bloque. Si el bloque FINALLY no existe, el programa ejecuta la primera sentencia despues de la clausula ENDTRY que marca el final de la estructura TRY...CATCH...FINALLY

Capturando el error

Cuándo el error ocurre, el código lanza (THROW) una excepción, el programa ejecuta la primera sentencia del bloque CATCH que maneja dicha excepción.

El programa examina las sentencias CATCH en la orden que estas aparecen para ver si una de ellas pueden manejar la excepción. Si el programa encuentra una sentencia CATCH que maneja la excepción, el programa ejecuta el código correspondiente.

La sentencia CATCH puede contener las clausuals opcionales TO y WHEN. Uno puede especificar una variable de memoria en la cláusula TO para almacenar una referencia a un objeto Exception (nuevo en Visual FoxPro 8), que se crea sólo cuando una excepción ocurre. Si se quiere establecer una condición para ejecutar un bloque CATCH, se puede especificar una expresión en la cláusula WHEN que se debe evaluar Verdadero (.T.) antes de que el bloque CATCH se ejecute.

Las sentencias CATCH trabajan similarmente como una sentencia DO CASE en el que la cláusula WHEN debe evaluar a una expresión lógica. Si las cláusulas TO y WHEN no existen, la sentencia CATCH se evalúa como CATCH WHEN .T. (Verdadero).

Después que el programa ejecuta las sentencias en un bloque CATCH, no vuelve a la sentencia TRY, y no busca otras declaraciones CATCH. El programa busca el bloque FINALLY, si este existe. Si no existe el programa ejecuta la sentencia inmediatemente despues de la clausula ENDTRY. El bloque FINNALY se ejecuta se haya o no generado una excepción.

Sintaxis y ejemplo

Esta es la sintaxis de la estructura de control TRY...CATCH...FINALLY

TRY
   [tryCommands] 
[CATCH [TO VarName] [WHEN lExpression] 
   [catchCommands]]
[THROW eUserExpression]
[EXIT]
[FINALLY 
   [finallyCommands]] 
ENDTRY

Un breve ejemplo del uso de TRY...CATCH...FINALLY

CLEAR
LOCAL ln AS Integer, lc AS Character
LOCAL lo AS Exception 
TRY
  ? "-- TRY --"
  SELECT 0
  USE "TablaNoExistente" ALIAS "MiTabla"
  GO BOTT
  ln = MiTabla.nCampo
  lc = MiTabla.cCampo
  ? ln
  ? lc
CATCH TO lo	&& objeto Exception
  ? "-- CATCH --"
  lo.UserValue = "Aquí hay un error"
  ? ' Comment: ', lo.COMMENT
  ? ' Details: ', lo.Details
  ? ' ErrorNo: ', lo.ErrorNo
  ? ' LineContents: ', lo.LineContents
  ? ' LineNo: ', lo.LINENO
  ? ' Message: ', lo.MESSAGE
  ? ' Procedure: ', lo.PROCEDURE
  ? ' UserValue: ', lo.UserValue
  ? ' StackLevel: ', lo.StackLevel
FINALLY
  ? "-- FINALLY --"
  IF USED("MiTabla")
    USED IN "MiTabla"
  ENDIF
ENDTRY
? "-- ENDTRY --"

Prioridad de los manejos de errores

Si un error ocurre en el método de un objeto que se llama en un bloque TRY, Visual FoxPro sigue el procedimiento del manejo del error para ese objeto particular. Este protocolo proporciona una manera para mantener una encapsulation y control de los componentes.

Por ejemplo, si la línea MiForm.Refresh() en un bloque TRY genera un error, si el método Error existe para manejar el error, entonces el método Error toma la precedencia. Si ningún método Error existe, entonces la sentencia CATCH procura manejar el error.

Veamos algunos ejemplos de estas prioridades:

Ejemplo 1: La clase MiClase posee un método Error, y este toma precedencia al generarse un error.

CLEAR
lo = CREATEOBJECT("MiClase")
lo.MiMetodo1()

DEFINE CLASS MiClase AS CUSTOM

  PROCEDURE MiMetodo1
    TRY
      THIS.MiMetodo2()
    CATCH TO loErr
      ? "-- CATCH --"
      ? "ErrorNo:", loErr.ErrorNo
      ? "LineNo:", loErr.LINENO
      ? "Procedure:", loErr.PROCEDURE
      ? "Message:", loErr.MESSAGE
    ENDTRY
  ENDPROC

  PROCEDURE MiMetodo2
    ? PROGRAM()
    *-- La variable luY no existe. El evento ERROR maneja este error.
    luX = luY
  ENDPROC

  PROCEDURE ERROR(nError, cProcedure, nLine)
    ? "-- ERROR --"
    ? "ErrorNo:", nError
    ? "LineNo:", nLine
    ? "Procedure:", cProcedure
    ? "Message:", MESSAGE()
  ENDPROC

ENDDEFINE

Ejemplo 2: La clase MiClase no posee un método Error, en esta caso el manejo de error lo maneja la claúsula CATCH.

CLEAR
lo = CREATEOBJECT("MiClase")
lo.MiMetodo1()

DEFINE CLASS MiClase AS CUSTOM

  PROCEDURE MiMetodo1
    TRY
      THIS.MiMetodo2()
    CATCH TO loErr
      ? "-- CATCH --"
      ? "ErrorNo:", loErr.ErrorNo
      ? "LineNo:", loErr.LINENO
      ? "Procedure:", loErr.PROCEDURE
      ? "Message:", loErr.MESSAGE
    ENDTRY
  ENDPROC

  PROCEDURE MiMetodo2
    ? PROGRAM()
    *-- La variable luY no existe y 
    *-- el método ERROR no existe. CATCH maneja este error.
    luX = luY
  ENDPROC

ENDDEFINE

Mas información

Pueden ver mas información de la estructura de control TRY...CATCH...FINNALY en:

Fox.Wikis: http://fox.wikis.com/wc.dll?Wiki~TryCatch


20 de noviembre de 2021

Controlar la configuración de un informe en tiempo de ejecución

Articulo original: Controlling report settings at run time
http://www.ml-consult.co.uk/foxst-12.htm
Autor: Mike Lewis
Traducido por: Luis María Guayán


Cómo permitir que los usuarios elijan opciones de impresora para informes VFP.

Este artículo se aplica a Visual Foxpro 8.0 y versiones anteriores. Si está utilizando una versión posterior, consulte la nota al final del artículo.

Probablemente sepa que, al diseñar un informe de Visual FoxPro, puede seleccionar el tamaño de página, la orientación y el origen del papel en el cuadro de diálogo "Configurar impresión". Este es el cuadro de diálogo al que llega cuando elige "Archivo" - "Configuración de página" y luego hace clic en el botón "Configurar impresión" dentro del diseñador de informes.

Pero hay un inconveniente. Si realiza algún cambio en la configuración de impresión de esta manera, sus usuarios no podrán anularlos en tiempo de ejecución.

Por ejemplo, si configura el origen del papel en "Bandeja superior", el informe siempre intentará seleccionar esa bandeja. No puede usar el comando REPORT FORM ... PROMPT para anularlo en tiempo de ejecución, porque el cuadro de diálogo PROMPT no incluye una configuración para el origen del papel. (Pero puede usar el cuadro de diálogo PROMPT para seleccionar una impresora diferente).

SYS(1037) tampoco ayudará. Normalmente, esa función muestra el cuadro de diálogo "Configurar página" y permite al usuario cambiar la configuración dentro de él. Los cambios afectarán a todos los resultados impresos de la sesión actual. Pero si cambió alguna de las configuraciones de página predeterminadas dentro del diseñador de informes, el cuadro de diálogo SYS(1037) no tendrá ningún efecto en ese informe. Ni siquiera puede usarlo para enviar el informe a una impresora diferente.

Hackear el FRX

Afortunadamente, existe una solución. Implica una pequeña triquiñuela tocando el archivo del informe.

Como ya se sabe, el formato interno de un informe de VFP, es decir, el archivo FRX, es el mismo que el de una DBF. De ello se deduce que se puede abrir el archivo como si fuera una tabla de FoxPro. También puede examinarlo y editarlo. Ahora, no es necesario que le digamos que editar un archivo de informe de esta manera es peligroso. Si cambia un campo incorrecto por un valor incorrecto, podría arruinar su diseño cuidadosamente planificado. Así que tenga cuidado con lo que sigue, y asegúrese de tener una copia de seguridad antes de comenzar.

El primer paso es deshacerse de la configuración de la impresora que se guardó en el diseñador de informes. Para hacerlo, abra y explore el informe desde la Ventana de Comandos. Por ejemplo, si el informe se llama Cliente, escriba lo siguiente:

USE Customer.frx
BROWSE

En la Ventana Examinar, busque un registro donde el campo Objtype sea igual a 1 y el campo Objcode igual a 53 (generalmente es el primer registro). En este registro, busque los campos Expr, Tag y Tag2. Estos son campos Memos que contienen la configuración que realizó en el cuadro de diálogo "Configuración de impresión" del diseñador de informes. Tag y Tag2 contienen valores binarios. Expr contiene texto sin formato, que se verá así:

DRIVER=WINSPOOL
DEVICE=HP LaserJet 6P/6MP - Enhanced
OUTPUT=LPT1:
ORIENTATION=0
PAPERSIZE=9
PAPERLENGTH=2794
PAPERWIDTH=2159
COPIES=1
DEFAULTSOURCE=4
PRINTQUALITY=-4
COLOR=2

Ahora siga adelante y elimine el contenido de estos tres campos Memo. Esto devolverá todas las configuraciones guardadas a sus valores predeterminados. Si desea permitir que el usuario elija el tamaño de la página, el origen del papel o la orientación en tiempo de ejecución, ahora puede llamar a SYS(1037) para hacer el trabajo.

Todo o nada

Pero, ¿qué sucede si desea permitir que el usuario cambie algunas de las configuraciones pero no otras? ¿O desea almacenar configuraciones no predeterminadas en el informe, pero desea permitir que el usuario las anule en determinadas circunstancias? Llamar a SYS(1037) no ayudará, porque es todo o nada. No puede usarlo para permitir que el usuario cambie algunas configuraciones, pero evitar que cambie otras. En cualquier caso, dicha función no funcionará si ha realizado algún cambio en la configuración desde el diseñador de informes, incluso si son diferentes de los que desea que el usuario configure.

Esto es lo que se haría. Supongamos que siempre desea que el informe se imprima en orientación horizontal en papel A5, pero desea permitir que el usuario cambie el origen del papel entre "Alimentación manual" y "Bandeja inferior".

Comience seleccionando la orientación y el tamaño de la página en el cuadro de diálogo "Configurar impresión" desde el diseñador de informes. Mientras esté allí, configure el origen del papel en el valor predeterminado que desee. Guarde el informe como de costumbre.

En su aplicación, proporcione al usuario un mecanismo para alternar el origen del papel. Puede ser un botón de comando, una casilla de verificación, un comando del menú o lo que sea. Cuando el usuario elija, ejecute un código similar al siguiente:

USE Customer.frx
LOCATE FOR Objtype = 1 AND Objcode = 53
REPLACE Tag WITH ""
REPLACE Tag2 WITH ""
IF "DEFAULTSOURCE=2" $ Expr
  lcNew = "DEFAULTSOURCE=4"
  lcOld = "DEFAULTSOURCE=2"
ELSE
  lcNew = "DEFAULTSOURCE=2"
  lcOld = "DEFAULTSOURCE=4"
ENDIF
REPLACE expr WITH STRTRAN(Expr,lcOld,lcNew)
USE

La próxima vez que se imprima el informe, seleccionará el origen de papel que elija el usuario.

Esto es lo que hace el código. Primero, abre el archivo del informe como una tabla y localiza el registro que contiene la configuración. Luego borra los valores binarios de la configuración. Eso no es un problema, el informe funcionará bien sin ellos.

A continuación, comprueba la configuración existente del origen de papel. Si es 2, lo cambia a 4 y viceversa. Como puede imaginar, esta configuración se especifica mediante el valor DEFAULTSOURCE: 4 significa "Alimentación manual", 2 es "Bandeja inferior". Finalmente, el campo Expr se actualiza con el valor modificado y se cierra el archivo.

¿Cómo supimos qué valores usar para DEFAULTSOURCE? Desde la pantalla de ayuda de la función PrtInfo(). La función PrtInfo(), devuelve la configuración de la impresora actual, utiliza los mismos valores que el campo Expr. Entonces, si desea comprender el contenido del campo, ahí es donde debe buscar.

Una última palabra: cuando distribuya su aplicación, asegúrese de excluir el archivo FRX y su archivo FRT asociado de la compilación. En otras palabras, no vincule estos dos archivos al archivo EXE. Si lo hiciera, el código anterior no podría actualizar los archivos y su usuario vería un error en tiempo de ejecución. En su lugar, déle al usuario una copia independiente de los dos archivos.

Nota para los usuarios de VFP 9.0:

En VFP 9.0, toda la cuestión de la configuración de la impresora en los archivos de informe se ha vuelto mucho más fácil. De hecho, nunca necesitará manipular el archivo FRX de la forma descrita en este artículo. De forma predeterminada, la configuración de la impresora ya no se guarda en el FRX. Independientemente de las configuraciones que estuvieran vigentes en el momento del diseño del informe, puede usar SET PRINTER TO NAME o SYS(1037) para establecer las configuraciones de tiempo de ejecución.

Si desea anular el comportamiento por defecto, es decir, si no desea guardar la configuración del informe en el archivo FRX, abra el menú Informe en el diseñador de informes, y seleccione la opción entorno de la impresora. Puede hacer esto si desea forzar la impresión de un informe en una impresora en particular, por ejemplo. Si desea que la configuración de la impresora se guarde en todos los informes de forma predeterminada, vaya a Herramientas - Opciones - Informes y habilite la opción "Guardar entorno de impresora".


Mike Lewis Consultants Ltd.

10 de noviembre de 2021

Separar párrafos en líneas de "n" caracteres

La función recursiva CortarParrafo() prepara una cadena para luego separarla con la función ALINES() en varias lineas de "n" o menos caracteres

Ejemplo:

lcCadena = "SON PESOS: TRES MILLONES NOVECIENTOS CINCUENTA Y CUATRO MIL " + ;
  "TRESCIENTOS OCHENTA Y NUEVE CON SETENTA Y CINCO CENTAVOS."

FOR ln = 1 TO ALINES(la,CortarParrafo(lcCadena,40))
  ? la(ln)
ENDFOR

FUNCTION CortarParrafo(tc,tn)
  LOCAL lc, ln
  tc = ALLTRIM(tc) + " "
  lc = SUBSTR(tc,1,tn)
  ln = RAT(" ",lc)
  lc = SUBSTR(lc,1,ln-1)
  RETURN IIF(EMPTY(lc),lc, lc + CHR(13) + CortarParrafo(SUBSTR(tc,ln+1),tn))
ENDFUNC

23 de octubre de 2021

Expresiones regulares en Visual FoxPro - Parte 3

Artículo original: Regular Expressions for Visual FoxPro Part 3
http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,9a28ad22-b41b-434a-a540-40e6197a099e.aspx
Autor: Craig Boyd
Traducido por: Ana María Bisbé York


FLL actualizada con más funcionalidad

No tengo tiempo (es tarde) para comentar mucho sobre los cambios que he hecho en regexp.fll. He mejorado significativamente las funcionalidades de la función regexp() cuando corta la cadena. Ahora se pueden guardar los pedazos cortados en una matriz o en un cursor. He mejorado además un par de errores en el código que tenían que ver con la fragmentación de la cadena. La documentación de mi entrada de blog anterior es válida para cada evento, vea (https://www.sweetpotatosoftware.com/blog/index.php/2006/01/11/regular-expressions-in-visual-foxpro-part-2/). (Nota del Editor: Traducido en este blog en Expresiones regulares en Visual FoxPro - Parte 2). Ahora se puede asignar 4 al parámetro nFunctionType y se obtendrá un cursor. Además, si está utilizando los valores 3 ó 4 para nFunctionType, puede especificar un comando de Visual FoxPro al motor de expresiones regulares para que lo ejecute cada vez que encuentre una coincidencia (pensado como una especie de función de rellamada -callback function )

Un ejemplo de análisis XML

Esta biblioteca ha tomado forma; pero pienso que existen muchas otras posibilidades que no se han explorado aun (Coméntenme en el blog o envíenme cualquier idea de funcionalidad que pueda tener -me encanta recibirlas). Algo nuevo que he pensado para la biblioteca puede ser análisis de XML. Utilicé alguna expresión regular que encontré disponible libremente en internet, creé un código de ejemplo (vea debajo) para mostrar las maravillosas habilidades de las expresiones regulares así como la nueva funcionalidad en la FLL.

Más por venir

Aun no he hecho justicia a las expresiones regulares ni a esta FLL. Cuando tenga más tiempo, regresaré a actualizar la documentación y mostrar cómo esta FLL ofrece posibilidades en Visual FoxPro que aun no hemos visto. He aquí un archivo de descarga y algunos ejemplos de código (la función ParseXML es lo fundamental que necesita la regexp.fll más reciente para poderla ejecutar). ¡¡ A disfrutar !!

Descarga de regexp.fll (63 KB aprox) haciendo clic aquí

*!* Ejemplo de empleo de la función ParseXML
#DEFINE CREATEANARRAY 2
#DEFINE CREATEACURSOR 3
LOCAL lcArrayToCreate, lcCursorToCreate, lnTotal, lnCounter
*!* He aquí un ejemplo de XML
*!* sólo como demostración
TEXT TO lcSampleXML NOSHOW PRETEXT 7
<?xml version="1.0"?>
<samples>
<sample>Visual FoxPro Rocks!</sample>
<sample>Hace mucho más antes de desayunar</sample>
<sample>que otros lenguajes hacen durante todo el día</sample>
</samples>
ENDTEXT

*!* O puede intentarlo utilizando un archivo XML
*!* Puede obtener algún ejemplo de XML desde
*!* ftp://sunsite.unc.edu/pub/sun-info/standards/xml/eg/shakespeare.1.01.xml.zip
*!* Una vez extraído comente del código encima TEXT/ENDTEXT 
*!* finalmente puede hacer algo como lo siguiente
*!* para cargar el ejemplo de archivos XML
*!* lcSampleXML = FILETOSTR(GETFILE())

*!* Crea una matriz
DIMENSION aryXMLDoc(1)
lcArrayToCreate = "aryXMLDoc"
lnTotal = ParseXML(lcSampleXML, lcArrayToCreate, CREATEANARRAY)
CLEAR
FOR lnCounter = 1 TO lnTotal
 ? aryXMLDoc(lnCounter)
ENDFOR
MESSAGEBOX("El XML analizado se mostrará en pantalla desde la matriz." ;
  + CHR(13) + "Oprima OK para continuar con el siguiente ejemplo.", ;
  64, "Análisis del XML terminado")

*!* Crea un cursor
lcCursorToCreate = "crsXMLDoc"
lnTotal = ParseXML(lcSampleXML, lcCursorToCreate, CREATEACURSOR)
IF lnTotal > 0
  GO TOP IN (lcCursorToCreate)
  BROWSE
ENDIF
MESSAGEBOX("Oprima OK para ejecutar el ejemplo final.", ;
  64, "Inicio del ejemplo final de Análisis del XML")

*!* Crea un cursor; pero además ejecuta código
*!* VFP  que ejecuta el  analizador C++.
*!* Puede ser utilizado para manipular el dato  
*!* como es recuperado, o lo que sea.
*!* El analizador C++ en la FLL
*!* ejecutará cualquier comando que se le indique
lcCursorToCreate = "crsXMLDoc"
lcVFPCommand = "DO AppendVFPRocks"
lnTotal = ParseXML(lcSampleXML, lcCursorToCreate, CREATEACURSOR, lcVFPCommand)
IF lnTotal > 0
  CLEAR
  GO TOP IN (lcCursorToCreate)
  SCAN ALL
    ? Splits
  ENDSCAN
ENDIF

**************************
PROCEDURE AppendVFPRocks
**************************
  Replace splits WITH "VISUAL FOXPRO ROCKS!" + splits
ENDPROC
*******************************
FUNCTION ParseXML (tcXML, tcName, tnType, tcCommand)
*******************************
*!* Esta función existe gracias 
*!* al trabajo de Robert Cameron...
*******************************
*!* REX/Perl 1.0 
*!* Robert D. Cameron "REX: XML Shallow Parsing with Regular Expressions",
*!* Technical Report TR 1998-17, School of Computing Science, Simon Fraser 
*!* University, November, 1998.
*!* Copyright (c) 1998, Robert D. Cameron. 
*!* El código siguiente puede ser utilizado libremente y distribuido indicando este
*!* copyright y citar en una nota que se mantiene intacta y si tiene modificaciones
*!* o agregados han de ser debidamente identificados.
*!* http://www.cs.sfu.ca/~cameron/REX.html
*******************************
*!* 01-14-2006: Traducidas y modificadas sus expresiones
*!* para uso en Visual FoxPro con regexp.fll
*!* por Craig Boyd http://www.sweetpotatosoftware.com/spsblog
*******************************
  LOCAL lcTextSE, lcUntilHyphen, ;
    lcUntil2Hyphens, lcCommentCE, lcUntilRSBs, ;
    lcCDATA_CE, lcS, lcNameStrt, lcNameChar, ;
    lcName, lcQuoteSE, lcDT_IdentSE, ;
    lcMarkupDeclCE, lcS1, lcUntilQMs, ;
    lcPI_Tail, lcDT_ItemSE, lcDocTypeCE, ;
    lcDeclCE, lcPI_CE, lcEndTagCE, lcAttValSE, ;
    lcElemTagCE, lcMarkupSPE, lcXML_SPE, ;
    lcExpression, lvReturn
  IF !("\REGEXP.FLL" $ SET("Library"))
    SET LIBRARY TO LOCFILE("regexp.fll", "FLL")
  ENDIF
  lcTextSE = "([^<]+"
  lcUntilHyphen = "[^-]*-"
  lcUntil2Hyphens = lcUntilHyphen + "(?:[^-]" + lcUntilHyphen + ")*-"
  lcCommentCE = lcUntil2Hyphens + ">?"
  lcUntilRSBs = "[^\]]*](?:[^\]]+])*]+"
  lcCDATA_CE = lcUntilRSBs + "(?:[^\]>]" + lcUntilRSBs + ")*>"
  lcS = "[ \n\t\r]+"
  lcNameStrt = "[A-Za-z_:]|[^\x00-\x7F]"
  lcNameChar = "[A-Za-z0-9_:.-]|[^\x00-\x7F]"
  lcName = "(?:" + lcNameStrt + ")(?:" + lcNameChar + ")*"
  lcQuoteSE = '"[^"]*"|' + "'[^']*'"
  lcDT_IdentSE = lcS + lcName + "(?:" + lcS + "(?:" + lcName + "|" + lcQuoteSE + "))*" 
  lcMarkupDeclCE = '(?:[^\]"' + "'><]+|" + lcQuoteSE + ")*>"
  lcS1 = "[\n\r\t ]"
  lcUntilQMs = "[^?]*\?+"
  lcPI_Tail = "\?>|" + lcS1 + lcUntilQMs + "(?:[^>?]" + lcUntilQMs + ")*>"
  lcDT_ItemSE = "<(?:!(?:--" + lcUntil2Hyphens + ">|[^-]" + lcMarkupDeclCE + ")|\?" ;
    + lcName + "(?:" + lcPI_Tail + "))|%" + lcName + ";|" + lcS
  lcDocTypeCE = lcDT_IdentSE + ;
    "(?:" + lcS + ")?(?:\[(?:" + lcDT_ItemSE + ")*](?:" + lcS + ")?)?>?"
  lcDeclCE = "--(?:" + lcCommentCE + ;
    ")?|\[CDATA\[(?:" + lcCDATA_CE + ")?|DOCTYPE(?:" + lcDocTypeCE + ")?"
  lcPI_CE = lcName + "(?:" + lcPI_Tail + ")?"
  lcEndTagCE = lcName + "(?:" + lcS + ")?>?"
  lcAttValSE = '"[^<"]*"|' + "'[^<']*'"
  lcElemTagCE = lcName + "(?:" + lcS + lcName + ;
    "(?:" + lcS + ")?=(?:" + lcS + ")?(?:" + lcAttValSE + "))*(?:" + lcS + ")?/?>?"
  lcMarkupSPE = "<(?:!(?:" + lcDeclCE + ")?|\?(?:" + lcPI_CE + ;
    ")?|/(?:" + lcEndTagCE + ")?|(?:" + lcElemTagCE + ")?))"
  lcXML_SPE = lcTextSE + "|" + lcMarkupSPE
  lcExpression = lcXML_SPE
  IF VARTYPE(tcCommand) = "C"
    lvReturn = RegExp(tcXML, lcExpression, tnType, tcName, tcCommand)
  ELSE
    lvReturn = RegExp(tcXML, lcExpression, tnType, tcName)
  ENDIF
  RETURN (lvReturn)
ENDFUNC

2 de octubre de 2021

Mejoras en el control Grid de Visual FoxPro

Artículo original: Visual FoxPro Grid Enhancements
https://www.sweetpotatosoftware.com/blog/index.php/2008/11/25/visual-foxpro-grid-enhancements
Autor: Craig Boyd
Traductor: Luis María Guayán

El control grid de Visual FoxPro

A menudo me han escuchado decir que el Grid de Visual FoxPro es uno de los mejores controles jamás ideados. Sigo sintiéndome así, pero ¿no sería bueno si algunas de las funciones que nuestros clientes quieren implementar en el control Grid ya estuvieran disponibles? Ya sabes, características como: ordenado, filtrado, búsqueda incremental, guardar las preferencias del usuario y exportar a Excel. Sería aún mejor si este tipo de funcionalidades pudiera implementarse en cualquier control Grid de Visual FoxPro (independientemente del origen de los registros) simplemente colocando una clase en un formulario, estableciendo una sola propiedad y escribiendo una sola línea de código. Bueno, eso es lo que me he propuesto crear con la clase que presento en esta publicación.

Pueden ver la funcionalidad básica proporcionada por GridExtras en las imágenes que aparecen al final de la publicación.

Cómo usar la clase

Les proporciono la aplicación Sample.exe en la descarga para que puedan probarla y ver cómo se implementa. Sin embargo, los pasos básicos son:

  • Coloque una instancia de GridExtras en su formulario o contenedor (un GridExtras para cada control Grid que desee mejorar).
  • Establezca la propiedad GridExpression de GridExtras en una cadena que se evaluará en tiempo de ejecución al control Grid que está mejorando: "Thisform.Grid1" es el valor predeterminado para esta propiedad.
  • Llame al método Setup() de GridExtras cuando su control Grid esté listo para funcionar. No tengo forma de saber si está configurando el origen de registros en tiempo de ejecución, o si está agregando columnas en el código, por lo que este método se proporciona como una forma de controlar cuándo GridExtras comenzará a interactuar con el control Grid
  • .

Eso es todo lo que hay que hacer para poner GridExtras en funcionamiento para un control Grid en su aplicación. Como digo, he incluido un ejemplo en la descarga, así que si tiene alguna pregunta sobre cómo se hace esto, simplemente revise el ejemplo.

Otras propiedades de la clase

Hay algunas otras propiedades de GridExtras de las que es posible que desee tomar nota y utilizar, como:

  • CompanyName y ProductName: estas propiedades se utilizan para determinar dónde guardar el archivo de preferencias del control Grid del usuario que está separado por perfil (Ej: "C:\Users\Craig\AppData\Roaming\MyCompany\MyProduct\gridprefs.tmp").
  • AllowGridExport, AllowGridFilter, AllowGridPreferences, AllowGridSort: estas propiedades le permiten activar o desactivar ciertas características de la clase según sus necesidades.
  • TemplateTable: esta propiedad determina dónde GridExtras busca gridextras.dbf que se usa para guardar las plantillas de Grid que crea el usuario (el usuario puede guardar sus filtros y ordenaciones para poder recrearlos fácilmente en un momento posterior). Es posible que deba establecer esta propiedad si planea mantener la tabla gridextras en una ruta de red, como con la carpeta de base de datos compartida para su aplicación.

Que sigue

Simplemente juegue con GridExtras y vea si es útil para usted y sus aplicaciones. En un mundo perfecto, encontraría alguna forma de mejorarlo (agregar formatos de exportación adicionales, proporcionar una función de bloqueo de columna, etc.). Si mejora GridExtras, le agradecería que se ponga en contacto conmigo y comparta las mejoras que ha implementado. Gracias de antemano a aquellos de ustedes que decidan hacerlo.

Hasta la próxima!

Descargar GridExtras y ejemplos (aproximadamente 223 KB)


Figura 1: GridExtras proporciona capacidades de ordenamiento, búsqueda incremental y filtrado a cualquier control Grid de Visual FoxPro.


Figura 2: GridExtras tiene características adicionales como la capacidad de volverse semitransparente y la capacidad de guardar las preferencias del usuario (orden de columna y ancho).


Figura 3: Además de las funciones proporcionadas por GridExtras a través de los encabezados de columna de un coltrol Grid, también hay un icono agregado en la parte inferior derecha de la clase que permite al usuario acceder a la pantalla "Plantillas de cuadrícula y exportación" que se ve en la Figura 4.


Figura 4: Las plantillas de Grids ayudan al usuario a guardar las vistas del Grid para poder recrearlas rápidamente en el futuro. La función de exportación de GridExtras puede crear formatos de Excel XLS, XLSX, XLB y XLM. Los títulos de encabezado del control Grid se utilizan para nombrar las columnas de Excel cuando se exportan los datos.