23 de marzo de 2011

La grandeza de VFP 9 viene en paquetes pequeños

Artículo original: Big VFP 9 thingd come in small package
Autor: Drew Speedie (QEPD)
Traducido por: Ana María Bisbé York

Nota de la traductora

Este texto corresponde a la sesión que fue preparada por el MS VFP MVP Drew Speedie para la Conferencia Southwest Fox 2005. Pocos meses antes de la conferencia, Drew Speedie falleció; pero su trabajo fue presentado por otro de los grandes de la comunidad VFP, el también MS VFP MVP, Andy Kramek.

Deseamos agradecer a Andy Kramek y Russ Swall de Vision Pace, donde trabajaba Drew Speedie, por la posibilidad que nos han brindado de distribuir la obra de Drew y que todos sigamos aprendiendo de el. Sirva este trabajo de traducción como homenaje de recordación a Drew Speedie. ¡Gracias Drew!

Resumen

Cada nueva versión de cualquier software contiene siempre varias "pequeñas" mejoras que no reciben mucha publicidad. Estos pequeños avances no merecen un tema para una hora de sesión en conferencias de desarrolladores. Sin embargo, si se agrupan todos juntos, comprenden una parte significativa de lo que vamos a utilizar a diario en el desarrollo de nuestras aplicaciones VFP 9.
Código de ejemplo Los archivos con código de ejemplo para esta presentación consta de un único archivo EXAMPLES.APP. Ejecute DO EXAMPLES, y el código de ejemplo para todos estos elementos se copiará en su disco en la misma carpeta que EXAMPLES.APP al seleccionar alguno de los botones Source (Código fuente) o Run (Ejecutar)
Palabra clave ADDITIVE para el comando SET PATH Agregar nuevas rutas al SET PATH actual ha sido siempre una tarea tediosa en VFP, típicamente lo hacíamos así:
LOCAL lcPath 
lcPath = SET("PATH") + ";C:\Projects\MyApp\Data"
SET PATH TO &lcPath 
En VFP 9, el comando SET PATH se ha mejorado para soportar la palabra clave ADDITIVE, por lo que se reduce a lo siguiente:
SET PATH TO "C:\Projects\MyApp\Data" ADDITIVE 
Todo lo que aparece a continuación funciona en VFP 9 para agregar una ruta por programa:
LOCAL lcDataPath
lcDataPath = "C:\Projects\MyApp\Data"
SET PATH TO (m.lcDataPath) ADDITIVE 
LOCAL lcDataPath
lcDataPath = ["C:\Projects\MyApp\Data"]
SET PATH TO &lcDataPath ADDITIVE 
LOCAL lcDataPath
lcDataPath = "C:\Projects\MyApp\Data"
SET PATH TO "&lcDataPath" ADDITIVE 
Cuando utiliza macrosustitución, se requiere el conjunto extra de delimitadores, debido a que en versiones anteriores ha podido asignar a SET PATH una carpeta llamada \ADDITIVE:
SET PATH TO ADDITIVE 
SELECT … WITH (BUFFERING = .T.) VFP 9 tiene muchas mejoras. Una de los que podría utilizar frecuentemente es la cláusula nueva WITH (Buffering = <lExpr>).

Antes de VFP 9, cuando el cursor (tabla, vista, etc) era guardado en buffer, la sentencia SELECT SQL siempre recibía los registros del disco. Los registros almacenados en buffer eran siempre ignorados, de tal forma que tenía que buscar otras vías para recibir los registros desde el cursor en buffer.

Esta mejora permite especificar si la sentencia SELECT va a utilizar los registros en buffer o los registros en disco; solamente añadiendo una cláusula WITH (Buffering = .T.) después de cada tabla deseada en la cláusula FROM ya el SELECT recibe los registros en buffer en lugar de los registros en disco.

Por ejemplo, he estado utilizando esta nueva cláusula para simplificar el código que recibía un registro de un cursor de tabla en buffer, para verificar algún valor. El código antiguo tenía este aspecto:
LOCAL lnRecno, lnSelect, lnValue
lnSelect = SELECT(0)
lnRecno = IIF(EOF(),0,RECNO())
SELECT TargetCursor
LOCATE FOR <SomeCondition>
lnValue = <SomeFieldValueOrWhatever>
IF m.lnRecno = 0
  GO BOTTOM
  IF NOT EOF()
    SKIP
  ENDIF
ELSE
  GOTO (m.lnRecno)
ENDIF
SELECT (m.lnSelect) 
...el código nuevo es este:
LOCAL lnValue
SELECT * FROM TargetCursor ;
  WITH (BUFFERING=.T.) ;
  FOR <SomeCondition> ;
  INTO CURSOR Junk
lnValue = <SomeFieldValueOrWhatever>
USE IN SELECT("Junk") 
O, ¿qué tal este código para obtener un cursor llamado InvoiceTotal del cursor LineItems (buffered) durante una entrada de datos:
SELECT SUM(Quantity*Price) AS TheTotal ;
  FROM LineItems WITH (BUFFERING=.T.) ;
  INTO CURSOR InvoiceTotal 
Notas:
  • Especificar WITH (Buffering=.F.) es lo mismo que omitir la cláusula WITH - tendremos el comportamiento predeterminado.
  • Cuando el cursor especificado en FROM no está almacenado en buffer, no hay ningún efecto al especificar WITH (Buffering=.T.), la cláusula es ignorada.
  • La cláusula WITH se aplica a nivel de tabla - específicamente para aquellas tablas del FROM, para las que desee ese comportamiento.
    Si está habilitado el buffer por filas, la ejecución de SELECT dispara un TABLEUPDATE() implícito para cada tabla con buffer de líneas en SELECT para las que ha especificado WITH (BUFFERING = .T.)
  • El nuevo comando SET SQLBUFFERING está igualado a OFF, póngalo en ON para especificar que todas las sentencias SELECT utilizan implícitamente WITH (BUFFERING = .T.) para todas las tablas en la cláusula FROM.
Se pueden realizar transacciones de tablas libres. VFP 9 agrega la posibilidad de realizar transacciones sobre tablas libres y cursores creados con CREATE CURSOR - las actualizaciones a los cursores pueden ejecutar ROLLBACK junto con todas las otras tablas contenidas y vistas en una transacción VFP.

Esta característica está basada en dos nuevas funciones:
  • MAKETRANSACTABLE()
  • ISTRANSACTABLE()
Un uso importante de esta nueva funcionalidad es en sistemas de herencia, donde debe actualizar una combinación, o para todas las tablas libres, o para alguna combinación de las tablas contenidas y las tablas libres, - antes, solamente las actualizaciones a tablas contenidas podían ser deshechas si fallaba la transacción.


15 de marzo de 2011

Saber la versión de un Libro de Excel

Con esta función podemos saber la versión con que fue guardado un libro de Excel.
lc = GETFILE("xls*")
? VersionLibroExcel(lc)

FUNCTION VersionLibroExcel(tcFile)
  LOCAL ln, lcFormat, lo
  IF NOT EMPTY(tcFile)
    lo = CREATEOBJECT("Excel.Application")
    lo.Workbooks.OPEN(tcFile)
    ln = lo.ActiveWorkbook.FileFormat
    DO CASE
      CASE ln = 16
        lcFormat = "Excel 2"
      CASE ln = 29
        lcFormat = "Excel 3"
      CASE ln = 33
        lcFormat = "Excel 4"
      CASE ln = 39
        lcFormat = "Excel 5 y 95"
      CASE ln = 43
        lcFormat = "Excel 97-2003 (Guardado desde 2003)"
      CASE ln = 51
        lcFormat = "Excel 2007-2010"
      CASE ln = 56
        lcFormat = "Excel 97-2003 (Guardado desde 2007-2010)"
      CASE ln = -4143
        lcFormat = "Excel 97, 2000, 2002 y 2003"
      OTHERWISE
        lcFormat = "Otro Formato # " + TRANSFORM(ln)
    ENDCASE
    lo.ActiveWorkbook.Close(.F.)
    lo.Quit
    lo = Null
  ELSE
    lcFormat = "No se especifico archivo"
  ENDIF
  RETURN lcFormat
ENDFUNC
Luis María Guayán