28 de julio de 2015

Utilizar un Select seguro para preservar los grids

Artículo original: Using a "Safe Select" to preserve your grid
http://weblogs.foxite.com/andykramek/2005/03/19/using-a-safe-select-to-preserve-your-grid
Autor:Andy Kramek
Traducido por: Ana María Bisbé York


Un problema común al trabajar con cursores locales en VFP es que cuando ellos se utilizan como origen para controles Grid, la recreación del cursor provoca que el grid pierda parte o toda su configuración. La razón 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 fácilmente demostrable, considerando lo siguiente:

*** Ejecutar un select básico 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 ejecución de la consulta crea un cursor nuevo que se abre con el mismo alias que el primero. Una comprobación rápida 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 específicas de las columnas se pierden y si el grid emplea columnas personalizadas o los controles han sido reemplazados por clases propias (o, desde la introducción de las clases member, en cualquier lugar que exista una clase member.) Por tanto, cualquier configuración específica se pierde y tiene que ser re-creada. ¡Esto, no es bueno!

Una solución al problema, que ofrezco con frecuencia en los foros on-line, es establecer la propiedad RecordSource del grid a una cadena vacía 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 razón para esta salvedad es que lo que ocurre en realidad en este caso es que al limpiar la propiedad RecordSource del grid, se limpia también 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 posición 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 continuación es que la persona que ha preguntado, trata la solución 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 metodología y que sustituya el cursor por una vista parametrizada. Esto es perfectamente válido y una vista parametrizada trabajará muy bien para estos casos.

Sin embargo, las vistas parametrizadas tienen una seria limitación. Debido a que las vistas deben estar pre-definidas, no es fácil crear una vista que acepte una condición de filtro para un propósito específico 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 combinación de First Name, LastName, Social Security Number, City, State, Order Number. Construir una vista parametrizada para controlarlo sería difícil, sino imposible.

Una solución para este problema es la técnica conocida como "select seguro".

La idea, es que debido a que los cursores se crean siempre en la estación 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 código 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 ningún efecto sobre ningún control (incluyendo grids) que utilice el cursor como origen de datos. Esta técnica 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 código cada vez que desea re-crear un cursor podría ser bastante tedioso; pero tenemos un entorno completamente orientado a objeto en VFP, porqué no agregar un método a  su formulario base que acepte dos parámetros - la cadena para la consulta y el nombre del cursor destino. Entonces, el código queda bien encapsulado y está disponible en cualquier forma que lo necesitemos. Puede incluso completar el código de tal forma que si el cursor destino no existe, sea creado por este método. He aquí mi método base "SaveSelect" con el que espero recibir una cadena de consulta que NO incluya una cláusula 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 cláusula READWRITE, si aun está utilizando una versión que no la soporte, existe una forma para hacerlo; pero  no lo diré porque se debe haber Actualizado. No hay ninguna razón para no haberlo hecho y sí muchísimas por las que debería - la principal es animar a Microsoft para que continúe desarrollando VFP, por ejemplo ...

26 de julio de 2015

Cambiar el aspecto de un formulario en Visual FoxPro

Artículo original: Skinning a Form in Visual FoxPro
http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,9a91dea3-6413-42e9-aeff-f0097937474d.aspx
Autor: Craig Boyd
Traducido por: Ana María Bisbé York


Hace un tiempo incorporé elementos VFPSkin en un proyecto en el que estaba trabajando. Fue entonces cuando apareció la primera versión de VFPSkin (versión 1.0?) y era gratis y con código abierto. Quedé muy impresionado con VFPSkin, nunca antes había visto aplicar estilos en VFP de esa forma. Tenía algunos problemas y le hice muchas modificaciones; pero la idea general era buena e ingeniosa. (Sólo para el registro, este escrito no apunta al código inicial de VFPSkin al escribir el ejemplo para esta entrada de blog. Admito haber estado expuesto al VFPSkin, y estar bajo su influencia; pero el código y las partes creadas para este ejemplo se crearon desde cero.)

Entonces, esto me motivó para aumentar mi trabajo sobre texturas en Visual FoxPro... hasta el día de hoy. Decidí buscar una forma creativa y simplificada de aplicar skins en las ventanas de Visual FoxPro. ¿Por qué? Bueno, como con todas mis ideas y proyectos, a veces por el cambio, y otras porque tuve una idea que puede ser útil en algo a la Comunidad de Visual FoxPro y la quiero explorar un poco. En este caso, es un poco de ambos. Llamo a este proyecto "Pantalla verde".

La idea fue tomar un bitmap único común que tiene un color único de fondo (la clave es transparente si desea), utilizarlo en la propiedad Picture del formulario, y luego, trabajar todo en tiempo de ejecución basado en ese único color. En este caso escogí verde para el color -como en las películas (allí fue donde tomé la idea, aunque en aquellos días pensaba que Hollywood usaba mayormente azul- y creé un ejemplo sencillo de piel que puedo utilizar en el desarrollo.


Green Screen Skin Bmp

Utilizando algunas llamadas a las funciones API (CreateRectRgn y CombineRgn, en GDI32 y SetWindowRgn en USER32) el proyecto progresó rápidamente y obtuve enseguida un formulario que mostraba justamente la porción necesaria de bitmap diseñado. Luego, llegó la hora de un código que permitiera a los desarrolladores Visual FoxPro utilizar sus propios bitmaps y crear "archivos de definición de diseños" basados en ellos. Decidí incorporar esta porción en mi formulario ejemplo también.

Esto es solamente un ataque inicial al tema ... lo considero una forma decente de probar el concepto. Mi objetivo final en esta etapa fue mostrar a los desarrolladores Visual FoxPro como los diseños pueden lograse de forma muy sencilla. Tomó mucho menos de un día llegar al resultado, así que imagine lo que puede hacerse teniendo tiempo. Luego, entró en mi lista de cosas por hacer la posibilidad de redimensionar el formulario (maximizar y minimizar) y la posibilidad de colocar o descolocar el diseño en dependencia de la capacidad de cambios de diseños al vuelo. Seguiré dando un vistazo a estas ideas, con esto quiero tener una herramienta que sea de muy sencilla aplicación para los desarrolladores Visual FoxPro.

Un par de notas finales: Los dos métodos en el formulario ejemplo que debe mirar son: createskindefinition y readskindefinition. Piense que emplee verde; pero puede ser cualquiera. El método readskindefinition va a mirar a un único pixel en la esquina superior izquierda de su bitmap para determinar el color que debe ser pintado en el formulario. Es todo, pienso que se puede sorprender de la cantidad mínima de código que hay para lograrlo. He aquí una imagen de la pantalla del ejemplo que está en el archivo de descarga.

Descargue el ejemplo Green Screen (10 KB aprox.)


23 de julio de 2015

Lo nuevo del Generador de Informes en VFP 9.0 - Parte 2

Articulo original: What's New in the Visual FoxPro 9.0 Report Writer
https://msdn.microsoft.com/en-us/library/ms965279.aspx
Autor: Cathy Pountney
Traducido por: Ana María Bisbé York


(Sesión What is new in the Visual FoxPro 9.0 Report Writer? presentada por la autora en la Conferencia DevEssentials Kansas, 2004)
... continuación del artículo Lo nuevo del Generador de Informes en VFP 9.0 - Parte 1

Mejoras en Agrupación de datos

Se han hecho un grupo de mejoras en los Grupos de datos (Data Groups) en el Generador de informes de VFP 9.0 (Report Writer).

Cantidad máxima de grupos de datos

La cantidad máxima depara grupos de datos se elevó de 20 a 74.

Columnas Horizontales

Previamente, los informes con más de una columna definida como horizontal con un Grupo de datos gastaban mucho espacio. La primera posición (fila 1, columna 1) dejaba un espacio en blanco y los datos comenzaban en la columna 2 de la fila 1. Además, una banda blanca se gastaba entre cada grupo de datos, como se muestra en la Figura 36. Incluso si la altura de la banda Encabezado de grupo (Data Group Header) es cero, VFP reservaba un espacio, como se muestra en la Figura 37.

Figura 36. Versiones anteriores de VFP gastaban mucho espacio en blanco al utilizar columnas horizontales con Grupos de datos.

Figura 37. Versiones anteriores de VFP reservaban espacio para la banda Encabezado de grupo, incluso, cuando no estuviera definida.
En VFP 9.0, cambió el comportamiento de los grupos de datos y las columnas horizontales. Cuando reencuentra un nuevo grupo de datos, lo imprime en la columna1 de la siguiente línea completa. El resto de esta fila se deja en blanco y no se utiliza para imprimir detalles. Los detalles pertenecientes a los Grupos de datos comienzan n la columna 1 de la fila inmediatamente después que se imprime la fila del grupo de datos, como se muestra en la Figura 38. Además no se reservan espacios extras para la altura de la banda Encabezado de grupo (Data Group Header), si la altura de la banda es cero, como se muestra en la Figura 39.

Figura 38. VFP 9.0 no gasta espacios como las versiones anteriores cuando se utilizan columnas horizontales y Grupo de datos.

Figura 39. VFP 9.0 no reserva espacios extras para la banda Encabezado de grupo si su altura es cero.
El comportamiento nuevo, aunque evita la situación descrita previamente, puede afectar a algunos informes existentes. Por lo tanto, un beneficio adicional del nuevo comportamiento es que la banda Grupo de datos puede expandirse a través de todas las columnas como se muestra en la Figura 40.

Figura 40. En VFP 9.0, puede expandir la banda Encabezado de grupo a través de múltiples columnas.

Múltiples bandas de detalle (Multiple-Detail Bands)

Además de las mejoras de extensibilidad en el Generador de Informes de VFP 9.0, la posibilidad de tener múltiples bandas de detalle es una de las mejoras más importantes y más solicitadas. Las nuevas características permiten procesar múltiples tablas hijas para cada registro de la tabla padre. Un ejemplo de este tipo de informe se muestra en la Figura 41.

Figura 41. Ejemplo de informe con múltiples bandas de detalles que tiene tres bandas de detalle separadas para cada Cliente (customer).

Tablas y relaciones

La clave para utilizar esta característica es comprender cómo trabajan juntas la tabla padre y las hijas. Como un ejemplo de escenario de múltiples bandas de detalle asuma que está escribiendo el informe mostrado en la Figura 41. La base de datos para este escenario se muestra en la Figura 42.

Figura 42. Un ejemplo de Base de datos de Clientes, Miembros, Vehículos y Viviendas (Customers, Members, Vehicles, Homes) para una compañía de seguros.
La tabla Customer es la tabla padre y contiene un registro para cada cliente de la compañía de seguros. Las tablas Members, Vehicles y Homes son las tablas hijas de la tabla Customer. La tabla Members guarda un registro para cada miembro de la familia del cliente. La tabla Vehicles guarda un registro para cada vehículo del cliente. La tabla Homes guarda un registro para cada vivienda del cliente.

Controlar el Informe

Es necesaria una tabla para manejar o conducir el informe. En este ejemplo, la tabla Customer es la tabla controladora. Si utiliza el Entorno de datos del informe para definir las tablas, establezca esta tabla para la propiedad InitialSelectedAlias. Si utiliza código para definir las tablas, asegúrese de que la tabla Customer está en el área de trabajo actual en el momento de ejecutar el informe.

El "Alias destino"

El target alias – tabla destino - es el término utilizado para describir qué tabla es la tabla conductora para una banda de detalle en particular. En este ejemplo, la tabla Members es el alias destino para la banda de detalle 1, la tabla Vehicles es el alias destino para la banda de detalle 2, y la tabla Homes es el alias destino para la banda de detalle 3.
Si no se define alias destino para una banda de detalle, el comportamiento es igual a las versiones anteriores de VFP. En otras palabras, una banda de detalle se procesa por el registro padre. Sin embargo, si escribe un nombre de tabla padre como alias destino, puede obtener resultados diferentes. Para cada registro de la tabla padre, VFP procesa todos los registros de la tabla padre, imprimiendo cada registro padre en la banda de detalle. Entonces, si tiene una tabla con 10 registros padres, y establece, alias destino de una banda de detalle igual a la tabla padre, el informe final imprimirá 10 conjuntos de 10 registros, un total de 100 registros.

Relaciones

Es importante darse cuenta de que las relaciones juegan una parte importante en cómo operan las múltiples bandas de detalle. VFP utiliza las relaciones entre la tabla padre y las tablas hijas para navegar por los registros. Puede utilizar SET RELATION o SET SKIP para definir estas relaciones. Si está abriendo las tablas en el Entorno de datos y las relaciones ya están definidas en la base de datos, las relaciones son respetadas.
Si está abriendo las tablas por código, el siguiente ejemplo muestra cómo establecer las tablas para el Informe de Clientes de la aseguradora mostrado en la Figura 41.
*-- Abrir las tablas hijas
USE Members IN 0 ORDER CustomerFK
USE Vehicles IN 0 ORDER CustomerFK
USE Homes IN 0 ORDER CustomerFK

*-- Abrir la tabla padre
SELECT 0
USE customer ORDER CustomerPK

*-- Establecer las relaciones entre la tabla padre y las hijas
SET RELATION TO CustomerPK INTO Members
SET RELATION TO CustomerPK INTO Vehicles ADDITIVE
SET RELATION TO CustomerPK INTO Homes ADDITIVE

*-- Ejecutar el informe
REPORT FORM Insurance PREVIEW 

Definir Múltiples bandas de detalle

De forma predeterminada, los informes nuevos, se crean con una sola banda.

Agregar bandas de detalle adicionales

Se agregan bandas de detalle adicionales desde el cuadro de diálogo Bandas opcionales (Optional Bands) mostrado en la Figura 43. Para invocar este cuadro de diálogo, seleccione Bandas opcionales... (Optional Bands...), desde el menú Informe (Report). Este es el mismo cuadro de diálogo que existía antes bajo el nombre Título / Resumen (Title/Summary). Fue renombrado para colocarle la opción adicional que se le agregó.

Figura 43. Utilice el control spinner Detalles (Details) del cuadro de diálogo Bandas Opcionales (Optional Bands) para ajustar la cantidad total de bandas de detalle.
Incremente el valor del control spinner Details hasta el número total de bandas que necesite en el informe. Puede definir hasta 20 bandas de detalle para cada informe. La Figura 44 muestra cómo el Diseñador de informe se encarga de crear tres bandas de detalle.

Figura 44. Este informe de ejemplo tiene definidas tres bandas de detalle

Definir el Alias destino

El alias destino se asigna a la banda de detalle desde el cuadro de diálogo Detalles (Detail) (vea la Figura 45). Este cuadro de diálogo es llamado al seleccionar Modificar bandas... (Edit Bands...), desde el menú Informe (Report) y seleccionar la banda de detalle aplicada. Puede además invocar este cuadro de diálogo al hacer doble clic en la barra gris de la banda de detalle aplicada.

Figura 45. Definir el "Alias destino" para cada banda de detalle en el cuadro de diálogo Detalle (Detail) correspondiente.
El Alias destino es una expresión; por tanto debe colocar el nombre de la tabla entre comillas. Una vez que haya definido cada alias destino, la barra gris que representa la banda de detalle muestra el alias destino (vea Figura 46).

Figura 46. El Diseñador de informes identifica cada banda con un número y con el alias destino asociado, de tal forma que se puede identificar fácilmente las diferentes bandas de detalle.
Al crear informes con múltiples bandas de detalle, es importante poner a cada campo el prefijo con el nombre del alias. Esto evita cualquier confusión con relación a la tabla de la que procede.

Encabezados y pies de bandas

Otra característica de las múltiples bandas de detalle es la habilidad para agregar encabezados y pies para cada banda de detalle. Son similares a los encabezados y pies de grupos en alguna medida, tienen algunas diferencias. Para cada registro padre que se procesa, ocurre lo siguiente:
  • Se procesa el encabezado de la banda 1.
  • Se procesa el detalle de la banda 1 una vez para cada registro hijo en el alias destino asociado.
  • Se procesa el pie de la banda 1.
  • Se procesa el encabezado de la banda 2.
  • Se procesa el detalle de la banda 2 una vez para cada registro hijo en el alias destino asociado.
  • Se procesa el pie de la banda 2.
  • Se procesa el encabezado de la banda 3.
  • Se procesa el detalle de la banda 3 una vez para cada registro hijo en el alias destino asociado.
  • Se procesa el pie de la banda 3.
Para activar los encabezados y pies de bandas, seleccione la casilla de verificación Encabezado / Pie de detalle (Detail Header/Footer) en el cuadro de diálogo Detalle (Detail) para cada una de las bandas de detalle (vea la Figura 45). Para ayudar a ordenar las bandas de detalle desde otras bandas, el triángulo que precede la banda está sólido, en lo que el resto de los triángulos son claros (vea la Figura 47).

Figura 47. La banda de detalle está marcada con triángulos sólidos y todas las otras bandas están marcadas con triángulos abiertos.
Además de identificar cada banda de detalle en el diseñador de informes, el cuadro de diálogo Modificar bandas (Edit Bands) indica además cada encabezado de banda de detalle, banda de detalle y pie de banda de detalle utilizando un número consecutivo de banda. El cuadro de diálogo Modificar bandas (Edit Bands) puede ser llamado seleccionando Modificar bandas... (Edit Bands...) desde el menú Informes (Report) (vea Figura 48).

Figura 48. El cuadro de diálogo Modificar bandas (Edit Bands) utiliza el número consecutivo de cada banda para ayudar a identificar cada banda de detalle, encabezado de banda de detalle y pie de banda de detalle.
Es importante notar que incluso si no hay registros en la banda detalles, de una banda en particular, el encabezado y pie de banda asociados se imprimirán. Si no desea imprimir los encabezados y pies de bandas en esas condiciones, puede utilizar la siguiente expresión para Imprimir cuando (Print when) en cada objeto definido en la banda para suprimir su impresión. Asegúrese además de activar, para cada objeto de la banda, la casilla de verificación Eliminar las líneas en blanco (Remove line if blank).
NOT EOF(<target alias>) 
Los encabezados y pies de banda de detalle tienen algunas de las mismas opciones de los encabezados y pies de grupo. Como se ve en la Figura 45, el cuadro de diálogo Detalle (Detail) tiene algunas opciones nuevas:
  • Comenzar en una columna nueva (Start on a new column): Utilice esta opción para hacer que el conjunto del detalle comience en una nueva columna del informe. Observe que esta opción le permite asignar específicamente un conjunto de detalle a una columna determinada. Si un conjunto de detalles tiene suficiente información que desborde la columna, entonces continúa en la columna siguiente.
  • Comenzar en una página nueva (Start on a new page): Utilice esta opción para hacer que el conjunto del detalle comience en una página nueva.
  • Reiniciar el número de página en 1 para cada conjunto de detalle (Reset page number to 1 for each detail set): Utilice esta opción, junto con la opción Comenzar en una página nueva (Start on a new page), para asignar el 1 al número de página para cada conjunto de detalle.
  • Comenzar un conjunto de detalle en una nueva página cuando quede menos de (Start detail set on new page when less than): Utilice esta opción para evitar bandas huérfanas. El conjunto de detalles comienza en una página nueva si no está disponible la cantidad de espacio indicada.
  • Encabezado / pie de detalle (Detail Header/Footer): Utilice esta opción para agregar un encabezado o pie de banda de detalle.
  • Re-imprimir el encabezado de banda en cada página (Reprint detail header on each page): Utilice esta opción junto con la opción Encabezado / Pie de banda de detalle para lograr que el encabezado de la banda de detalle se reimprima siempre que el conjunto de detalles sobrepase una página.

Variables y Cálculos del informe

Con la introducción de las múltiples bandas de detalle, las variables y cálculos del informe tienen algunas peculiaridades. Es necesario entender completamente como se procesan para utilizarlas con eficiencia. De otro modo, puede obtener resultados inesperados.
El cuadro desplegable Reiniciar en (Reset at) en el cuadro de diálogo Variables del informe (Report Variables) se ha renombrado como Reiniciar basado en (Reset based on). De esta forma se define más claramente que la variable se reinicia basada en los cambios del valor de la opción seleccionada. Además de renombrar el control, si se define en el informe más de una banda, cada banda de detalle se agrega al cuadro desplegable. Vea en la Figura 49 el nuevo cuadro de diálogo para Variables del informe (Report Variables).

Figura 49. Las variables calculadas en el informe tiene algunas opciones nuevas en “Reiniciar basado en” ("Reset based on").
Al seleccionar (Detail on) como valor de Reiniciar en base a (Reset based on), indica a VFP que procese este cálculo sólo para los registros del alias destino de esta banda de detalle. La variable de informe no se altera mientras se procesan los registros en otros alias destino. Esto permite amarrar una variable de informe para una banda de detalle en particular. El valor de la variable no se limpia hasta que el encabezado de esa misma banda de detalle se procesa para el siguiente registro de la tabla padre.
Si selecciona otro valor en Reiniciar en base a (Reset based on) diferente a una banda de detalle, el cálculo se procesa en varios lugares. Primero, se aplica el cálculo para cada registro padre. Segundo, se aplica para cada registro en el alias destino de la primera banda de detalle. Luego, se aplica el cálculo para cada registro en el alias destino de la segunda banda de detalle, etc.
En el informe de dos páginas mostrado en la Figura 50, puede ver un ejemplo de variables de informe calculadas asociadas con bandas de detalle individuales. Puede ver además el Total de registros procesados (Total records processed) al final del informe muestra un valor de 20. Este número representa el total de miembros procesados Members (7), más el total de vehículos procesados Vehicles (7), más el total de viviendas procesadas Homes (3), más el total de clientes procesados Customers (3).


Figura 50. Las variables de informe calculadas se pueden asociar a una banda de detalle o se pueden aplicar a todos los registros procesados.

Misceláneas

Existen algunos elementos adicionales que deben ser explicados en el tema de las múltiples bandas de detalle.

Almacenamiento en el FRX

Las bandas se almacenan en el FRX con OBJTYPE igual a 9, y un valor de OBJCODE que determina qué tipo de banda es. El encabezado de detalle se guarda con 9 para OBJCODE, y el pie de detalle con OBJCODE igual a 10.La nueva expresión para alias destino se guarda en el campo EXPR del registro correspondiente a la banda de detalle.

SUMMARY

Utilizar la cláusula SUMMARY en el comando REPORT FORM evita imprimir la banda de detalle, no así todos los encabezados y pies de páginas, encabezados y pies de columnas y encabezados y pies de grupos. Cualquier expresión On Entry u On Exit en la banda de detalle no se procesa cuando se utiliza la cláusula SUMMARY. Al utilizar la cláusula SUMMARY en un informe con múltiples bandas de detalle, los encabezados y pies de bandas de detalle y las bandas de detalle no se procesan.

Mucho que aprender

Hacerse con el control de las múltiples bandas de detalle puede tomar un tiempo. Hay que entender cómo trabajan todas las tablas juntas, saber qué es un alias destino, y entender la relación entre las tablas. Debe tener también el control sobre cómo se afectan las variables y los cálculos por las múltiples bandas de detalle. Puede que necesite leer esta sección más de una vez antes de entenderlo del todo.

La tabla FRX

Para mantener compatibilidad hacia atrás, el Generador de informes de VFP 9.0 utiliza la misma estructura que versiones anteriores. Para cada registro del FRX, los campos OBJTYPE y OBJCODE se utilizan juntos para definir qué tipo de data contiene el registro. No todos los campos del FRX se aplican a todos los tipos de registro. Por tanto, para acomodar todas las características nuevas del generador de informes, los campos existentes son sobrecargados cuando es necesario.
Otro cambio clave en el Informe de VFP 9.0 es la forma en que se trata el campo USER. Antes de VFP 9.0, era borrado cualquier dato guardado en el campo USER. Este comportamiento anulaba el propósito del campo USER y lo hacía inútil. En VFP 9.0, cualquier dato guardado en el campo USER se guarda y se deja sólo. Se pueden crear campos adicionales en el FRX, ya que son agregados al final del FRX. Cualquier campo adicional es retenido por VFP y no será eliminado.
Además de mantener el campo USER, el Generador de informes de VFP 9.0 retiene también todos los registros de tipos desconocidos. En lugar de eliminarlos del FRX, el Generador de informes retiene estos registros al final del FRX y los ignora durante el procesamiento. Esto brinda la capacidad de agregar sus propios tipos de registro para procesamientos especiales.
Teóricamente, puede además escribir informes en VFP 9.0, y como no está utilizando nada nuevo, puede ejecutar los informes en versiones anteriores de Visual FoxPro. Por supuesto, si agrega nuevos campos o registros al FRX, se destruyen si modifica o guarda el informe en una versión anterior de VFP.

Los registros

Existen diferentes tipos de registros guardados en el metadato del informe. El campo OBJTYPE identifica el tipo de cada registro y el resto de la información del registro varía grandemente, en dependencia del OBJTYPE. En otras palabras, los campos en la tabla tienen múltiples propósitos y necesita conocer el OBJTYPE para descifrar el significado del resto del registro.
Los tipos válidos son los siguientes:
  • Report definition (OBJTYPE = 1): El primer registro en la tabla es el registro de definición de informe. Contiene información general sobre el informe, como puede ser información de impresión e información de configuración de página. Existe un registro de definición de informe por cada tabla.
  • Report objects: Algunos tipos de objetos diferentes son utilizados como formas, texto, datos y gráficos en un informe. Colectivamente, estos objetos se referencias como objetos de informe (Report objects) y tienen los siguientes tipos:
    • Label (OBJTYPE = 5): Un objeto etiqueta (label) es un término utilizado para describir una pieza estática de texto colocada en un informe. Es utilizado comúnmente para títulos de informe, títulos de columnas, nombres de compañías, y otra información que no cambia cada vez que se imprime el informe. Cada objeto label en un informe se representa por un registro de la tabla.
    • Line (OBJTYPE = 6): Un objeto línea (line) es utilizado para representar líneas horizontales y verticales en un informe. Cada objeto line en un informe se representa por un registro de la tabla.
    • Shape (OBJTYPE = 7): Un objeto forma (shape) se utiliza para representar rectángulos y rectángulos redondeados en un informe. Cada shape en un informe se representa por un registro de la tabla.
    • Field (OBJTYPE = 8): Un objeto campo (field) es uno de los objetos más comúnmente utilizados en un informe. Se utiliza para imprimir datos en un informe. Los datos pueden ser un campo de una tabla o el resultado de una expresión. Se puede utilizar incluso cálculos internos que trae el Generador de informes de VFP para obtener los resultados. Cada field en un informe se representa por un registro de la tabla.
    • Picture (OBJTYPE = 17): Un objeto imagen (picture) se utiliza para representar un control Picture/ActiveX Bound en un informe. Cada Picture/ActiveX en un informe se representa por un registro de la tabla.
  • Band (OBJTYPE = 9): Un objeto banda band) se utiliza para representar una banda individual de un informe. Como mínimo, todos los informes tienen tres objetos de banda: encabezado de página, detalle y pie de página (page header, detail, y page footer). Un informe puede contener además varias bandas opcionales título, encabezado de columna, encabezado de grupo, pie de columna, pie de grupo, resumen, encabezado de detalle y pie de detalle (title, column header, data group header, column footer, data group footer, summary, detail header, y detail footer).
  • Group (OBJTYPE = 10): Un objeto grupo (group) se utiliza para representar un grupo de objetos de informe que han sido agrupados juntos utilizando la opción Agrupar (Group) del menú Formato (Format) desde el Diseñador de informe (no confundir con las agrupaciones de datos).
  • Variable (OBJTYPE = 18): Un objeto variable se utiliza para representar una variable individual del informe. Cada variable en un informe se representa por un registro de la tabla.
  • Font (OBJTYPE = 23): Un objeto fuente (font) se utiliza para representar una única fuente utilizada en cualquier lugar del informe. Cada tipo diferente de fuente del informe es representada por un registro de objeto font. Como mínimo, existe un objeto font (para la fuente predeterminada).
  • Data Environment (OBJTYPE = 25): Un objeto entorno de datos (data environment) se utiliza para representar el entorno de datos de un informe. Todas las propiedades y métodos del entorno de datos se almacenan en este registro. Existe un registro data environment para cada tabla FRX.
  • Data (OBJTYPE = 26): Un objeto dato (data) se utiliza para representar lo mismo un objeto cursor o un objeto relación. Cada objeto cursor o relation que esté definido en el Entorno de datos de un informe se representa por un registro de la tabla.
Los registros se colocan en la tabla en un orden físico específico y es importante respetar ese orden si se agregan nuevos registros mediante programación. Puede utilizar el comando SORT para copiar los registros a tablas temporales y luego devolverlos a la tabla del informe en el orden correcto, que es el siguiente:
  • Registro Definición de informe (OBJTYPE = 1)
  • Registros de bandas (OBJTYPE = 9). Las bandas se agregan a la tabla en orden ascendente del campo OBJCODE, con las siguientes excepciones:
    • Cuando se definen en el informe múltiples grupos de datos...
      ...las bandas encabezado de grupo (objcode = 3) se agregan en el mismo orden en el que aparecen en el cuadro de diálogo Agrupar datos Data Grouping.
      ...las bandas pie de grupo (objcode = 5) se agregan en el orden opuesto al que aparecen en el cuadro de diálogo Agrupar datos.
    • Cuando se definen múltiples bandas de detalle en un informe, la primera banda de detalles, las bandas encabezado, detalle y pie se agregan como un conjunto. Entonces, se agrega el conjunto de bandas de la segunda banda de detalle, etc.
  • Los objetos del informe (OBJTYPE = 5, 6, 7, 8 y 17) se agregan en el orden de su Z-Order, donde el objeto que se encuentra arriba de todos se agrega primero.
  • Registros de objetos Grupo (OBJTYPE = 10)
  • Registros de variables de informe (OBJTYPE = 18). Los registros de variable de informe se agregan a la tabla en el mismo orden que aparecen en el cuadro de diálogo Variables de informe (Report Variable).
  • Registros de fuente (OBJTYPE = 23)
  • Registros de entorno de datos (OBJTYPE = 25)
  • Registros de datos (OBJTYPE = 26) se agregan en el orden en que son agregados al entorno.

La unidad de medida

Visual FoxPro utiliza su propia unidad de medida FoxPro Report Units (FRU), al referirse al tamaño y ubicación de los objetos en el informe. Si el sistema está fijado en pulgadas, la unidad de medida es 1/10,000 de una pulgada. Si el sistema está fijado en centímetros, la unidad de medida es 1/1,000 de un centímetro.

La posición

No existen campos en la tabla que representen a que banda pertenece cada objeto. En su lugar Visual FoxPro determina la banda calculando la altura definida para cada banda, el VPOS del objeto y entonces determina en que banda entra un VPOS determinado.
Al mirar a la altura de cada banda, sin embargo VFP toma en cuenta la altura de la banda gris horizontal que representa cada banda al mostrarlo en la pantalla en el Diseñador de informes. El valor para la altura de la banda gris es 2083.33333333 al utilizar pulgadas y 529.16666667 al utilizar centímetros.

Los campos

Describir lo que representa cada campo es difícil porque los campos pueden ser utilizados con diferentes propósitos, en dependencia del OBJTYPE particular para cada registro. La Tabla 2 lista cada campo y el significado para los diferentes tipos de objetos.
Además de la Tabla 2, Microsoft proporciona una DBF que contiene información sobre las tablas FRX. Esta DBF ha sido actualizada para VFP 9.0 y se localiza en el directorio HOME() + 'toolsfilespec'.

CampoOBJTYPEDescripción
PLATFORMTodosSiempre "WINDOWS"
UNIQUEIDTodos excepto:
0-Comment
23-Font
25-Data Environment
26-Data
Es el identificador único de la mayoría de los registros. Puede utilizar SYS(2015) para crear un valor personalizado al agregar registros.
TIMESTAMPTodos excepto:
21-Printer driver (2.x)
23-Font
25-Data Environment
26-Data
Información sobre cuándo fue modificado el registro por última vez.
OBJTYPE0-49 reservados para uso nativo.
50-99 disponibles para uso del usuario.
0 = Comment
1 = Report Definition
2 = Work area (2.x reports)
3 = Index (2.x reports)
4 = Relations (2.x reports)
5 = Label
6 = Line
7 = Shape
8 = Field
9 = Band
10 = Grouped objects (no Data Groups)
17 = Picture / OLE Bound
18 = Variable
21 = Printer driver setup (2.x reports)
23 = Font
25 = Data Environment
26 = Data (Cursor, Relation, o cursor adapter)
OBJCODECuando el campo OBJTYPE no es suficiente para identificar un tipo de registro, se utiliza el campo OBJCODE para identificación adicional del registro.
1-Report DefinitionSiempre 53.
2-Work area (2.x)Área de trabajo de la tabla.
3-Index (2.x)Área de trabajo del IDX.
4-Relation (2.x)Área  de trabajo de tabla hija.
5-Label
6-Line
8-Field
10-Group
17-Picture
Siempre 0.
7-ShapeSiempre 4.
9-BandDescribe el tipo de banda:
0 = Title
1 = Page Header
2 = Column Header
3 = Group Header
4 = Detail
5 = Group Footer
6 = Column Footer
7 = Page Footer
8 = Summary
9 = Detail Header
10 = Detail Footer
NAME2-Work area (2.x)Nombre del archivo de la tabla.
3-Index (2.x)Nombre del archivo IDX.
8-FieldEncabezado en tiempo de diseño.
17-PictureSi se define como Imagen desde archivo (Picture from File), y se selecciona un archivo de imagen (picture file), está en blanco.
Si se define como Imagen desde archivo (Picture from File), y se introduce una expresión, contiene la expresión.
Si se define como (Picture from Field), contiene el nombre del campo general.
18-VariablesNombre de las variables.
21-Printer driver (2.x)Nombre de la impresora configurada.
25-Data Environment"dataenvironment"
26-Data"cursor" para cursores
"relation" para relaciones
"cursoradapter" para cursor adapters
EXPR1-Report DefinitionInformación del Controlador de impresora (Printer driver) y la configuración de impresora.
3-Index (2.x)Expresión de orden.
4-Relation (2.x)Expresión de relación.
5-LabelTexto de los objetos etiqueta (Label).
8-FieldExpresión de objeto campo (Field).
9-Band/Group HeaderExpresión de Agrupación de datos (Data Group).
9-Band/DetailExpresión de Alias destino.
18-VariablesExpresión de Almacenar valor (Value to store).
25-Data Environment
26-Data
Propiedades del Entorno de datos o del objeto Data.
VPOS1-Report DefinitionCantidad de conjuntos de columnas.
10-GroupEste número representa el primer objeto incluido en este grupo. Se basa en el Z-Order de los objetos del informe. Sin embargo, los objetos agrupados pueden pertenecer a otros objetos agrupados. Cuando ocurre esto, el grupo de objetos entero se cuenta únicamente una vez que se haya determinado este número.
23-FontAltura de los caracteres, en pixels, FONTMETRIC(1).
Report objectsPosición vertical de los objetos, en FRUs.
HPOS1-Report DefinitionMargen izquierdo, en FRUs.
Relativo al margen de impresión si se selecciona Página imprimible (Printable page).
Relativo al borde físico del papel si se selecciona Toda la página (Whole page).
10-GroupEste número representa el total de objetos de informe en este grupo. Sin embargo si los objetos agrupados se incluyen en otro grupo, todo el grupo se cuenta como un único objeto.
23-FontEl ancho promedio de los caracteres en pixels, FONTMETRIC(6).
Report objectsPosición horizontal de los objetos en, FRUs.
HEIGHT1-Report DefinitionEspacio entre columnas, en FRUs.
9-BandAltura de la banda, en FRUs.
23-FontLo que sube el carácter en pixels, FONTMETRIC(2).
Report objectsAltura de los objetos, en FRUs.
WIDTH1-Report DefinitionAncho de cada columna, en FRUs.
9-Band/Detail
9-Band/Group Header
Valor de Comenzar grupo en nueva página cuando se menor que (Start group on new page when less than) en el cuadro de diálogo Agrupr datos (Data Grouping) del cuadro de diálogo Detalle (Detail), en FRUs.
23-FontAncho máximo de caracteres en pixels, FONTMETRIC(7).
Report objectsAncho de los objetos, en FRUs.
STYLE1-Report DefinitionSi el informe utiliza una clase DataEnvironment o ha copiado el Entorno de datos de otro informe, contiene el XML con el entorno de datos.
2.x report objectsB = Negrita - Bold
I = Cursuva - Italic
R = Sobreíndice - Raised
L = Subíndice - Lowered
J = Alineada a la derecha
C = Alineada al centro
PICTURE5-LabelContiene el formato de alineación de los caracteres.
8-FieldExpresión escrita en el cuadro de texto Formato (Format) en el cuadro de diálogo Expresión de informe (Report Expresión). Si se selecciona  Interleave, la expresión de formato inicia con @R.
17-PictureSi se definió como Picture from File, y se escogió un archivo de imagen, este contiene la ruta relativa y nombre del archivo.
Si se definió como Picture from File, ay se introduce una expresión, está en blanco.
Si se definió como Picture from Field, está en blanco.
ORDERTodos—anterior a  VFP 9.0No se utiliza.
Todos—VFP 9.0Continene un valor de caracteres que representa un valor numérico (las marcas binarias sumadas) para identificar niveles de protección.
Objectos (bit, valor, significado)
0, 1, Lock (movido o redimensionado)
1, 2, Hide (visible)
2, 4, No eliminar
3, 8, No modificar
6, 64, No seleccionar
Bandas (bit, valor, significado)
4, 16, No modificar
14, 16384, No redimensionar
Informe (bit, valor, significado)
7, 128, No hacer presentación preliminar
8, 256, No permitir bandas opcionales
9, 512, No permitir agrupaciones de datos
10, 1024, No permitir variables
11, 2048, No mostrar Configurar página
12, 4096, No permitir selección múltiple
13, 8192, No mostrar Entorno de datos
15, 32768, No imprimir
16, 65536, No permitir Informe rápido
UNIQUE1-Report Definition.T. = Informe generado temporalmente por el asistente 
.F. = Informe permanente
2-Work area (2.x).T. = Existe un índice activo para esta área de trabajo
.F. = No existe un índice activo para esta área de trabajo
18-VariableSe corresponde con la casilla de verificación Liberar tras informe (Release after report) en el cuadro de diálogo Variables de informe (Report Variables).
COMMENTTodosSe corresponde con el cuadro de edición Comentarios (Comments).
ENVIRON25-Data Environment.T. = Sesión de datos Privada
.F. = Sesión de datos Predeterminada
BOXCHARTodosNo se utiliza
FILLCHAR8-FieldC para campos de caracteres.
N para campos numéricos.
D para campos Fecha.
TAG1-Report DefinitionInformación binaria del controlador de impresora.
2-Work area (2.x)Alias del área de trabajo.
9-BandValor de la expresión Al entrar (On Entry).
18-VariableValor inicial (Initial value).
25-Data Environment
26-Data
Contiene el código de eventos y métodos.
TAG21-Report DefinitionInformación binaria del controlador de impresora.
9-BandValor de la expresión Al salir (On Exit).
25-Data Environment
26-Data
Contiene el código compilado de eventos y métodos.
PENRED23-FontLo que baja el carácter en pixels, FONTMETRIC(3).
Report objectsColor de primer plano Red como en RGB().
PENGREEN23-FontMargen extra en pixels, FONTMETRIC(5).
Report objectsColor de primer plano Green como en RGB().
PENBLUEReport objectsColor de primer plano Blue como en RGB().
FILLREDReport objectsColor de fondo Red como en in RGB().
FILLGREENReport objectsColor de fondo Green como en RGB().
FILLBLUEReport objectsColor de fondo Blue como en RGB().
PENSIZE6-Line
7-Shape
Tamaño del borde (cuando selecciona Borde (Pen) desde el menú Formato (Format) y escoge uno de los trazos de línea sólida).
0 = Trazo fino
1 = 1 Punto
2 = 2 Puntos
4 = 4 Puntos
6 = 6 Puntos
El ancho completo de la línea no será visible a menos que altura HEIGHT o ancho WIDTH sea (PENSIZE x 104.167).
PENPAT6-Line
7-Shape
Patrón de línea (Seleccionar Borde (Pen) en el menú Formato (Format) y escoger uno de los bordes con línea no sólida).
0 = Ninguno (None)
1 = Punteado (Dotted)
2 = Con guión (Dashed)
3 = Guión-Punto (DashDot)
4 = Guión-Punto-Punto (DashDotDot)
8 = Normal/Sólido (Normal/Solid
FILLPAT7-ShapePatrón de relleno (Seleccionar Relleno (Fill) del menú Format (Format).
0 = Ninguno
1 = Sólido
2 = Líneas horizontales
3 = Líneas verticales
4 = Líneas diagonales, ladeadas a la izquierda
5 = Líneas diagonales, ladeadas a la derecha
6 = Cuadrícula (líneas horizontales y verticales)
7 = Trama (líneas diagonales a izquierda y derecha)
FONTFACE1-Report DefinitionNombre de la fuente para la Fuente predeterminada.
5-Label
8-Field
23-Font
Nombre de la fuente.
FONTSTYLE1-Report Definition
5-Label
8-Field
23-Font
0 = Normal
1 = Negrita (Bold)
2 = Cursiva (Italic)
4 = Subrayada (Underlined)
128 = Tachada (Strikethrough)
Los números pueden combinarse para lograr múltiples estilos de fuente.
FONTSIZE1-Report Definition
5-Label
8-Field
23-Font
Tamaño de la fuente.
MODEReport objectsModo (Mode)
0 = Opaco
1 = Transparente
Orden de lectura (Reading Order)
0 = De izquierda a derecha
2 = De derecha a izquierda
4 = Contextual
Los valores de Modo y Orden de lectura se agregan juntos.
RULER1-Report Definition0 = Sin regla
1 = La medida de la regla es pulgadas
2 = La medida de la regla es métrica
3 = La medida de la regla es pixels
4 = La medida de la regla es carácter (1/12")
5 = La regla respeta el sistema predeterminado actual
RULERLINES1-Report Definition0 = No muestra las Líneas de cuadrícula en el Diseñador de informes
1 = Muestra las Líneas de cuadrícula en el Diseñador de informes
8-FieldSe corresponde con la opción Modo de recorte para expresiones de caracteres (Trim mode for character expressions) del cuadro de diálogo Formato (Format).
0 = Recorte predeterminado  (Default trimming)
1 = Recortar al carácter más cercano (Trim to nearest character)
2 = Recortar a la palabra más cercana (Trim to nearest word)
3 = Recortar al carácter más cercano con puntos suspensivos adicionales (Trim to nearest character, append ellipsis)
5 = Especificar nombre de archivo como puntos suspensivos (Show inner path as ellipsis)
6 = Recortar a la palabra más cercana con puntos suspensivos adicionales (Trim to nearest word, append ellipsis)
GRID1-Report Definition.T. = Está activado Ajustar a la cuadrícula (Snap to Grid)
.F. = No está activado Ajustar a la cuadrícula
GRIDV1-Report DefinitionEspacio vertical de las líneas de cuadrícula, en pixels.
GRIDH1-Report DefinitionEspacio horizontal de las líneas de cuadrícula, en pixels.
FLOATReport objectsValor de la opción Flotante (Float) del cuadro del diálogo Propiedades (Property) del objeto.
STRETCH6-Line
7-Shape
Valor de la opción Expandir relativo a la altura de la banda flotante (Stretch relative to height of band Float) del cuadro del diálogo Propiedades (Property) del objeto.
8-FieldValor de la opción Ajustar al contenido del texto Expandir con desbordamiento (Stretch with overflow) del cuadro del diálogo Propiedades (Property) del objeto 
STRETCHTOP6-Line
7-Shape
Valor de la opción de la casilla de verificación Expandir relativo al objeto más alto del grupo (Stretch relative to tallest object in group) del cuadro del diálogo Propiedades (Property) del objeto
TOP1-Report Definition.T. = El área imprimible es Toda la página  (Whole page)
.F. = El área imprimible es Página imprimible (Printable page)
Report objectsSe corresponde con el valor de la opción (Fix relative to top of band) en el cuadro de diálogo (Property) para el objeto
BOTTOM1-Report Definition.T. = Conjunto de múltiples columnas se imprimen en el orden de izquierda a derecha
.F. = Conjunto de múltiples columnas se imprimen en orden de arriba a abajo
Report objectsSe corresponde con el valor de la opción Fijar relativo al inicio de banda (Fix relative to bottom of band) en el cuadro de diálogo Propiedades (Property).
SUPTYPETodosNo se utiliza.
SUPRESTTodosNo se utiliza.
NOREPEATReport objectsSe corresponde con el valor de la casilla de verificación Quitar líneas en blanco (Remove line if blank) en el cuadro de diálogo Imprimir cuando (Print when).
9-Bands/DetailSe corresponde con el valor de la casilla de verificación Repetir encabezado de detalle en cada página (Repeat detail header on each page) en el cuadro de diálogo Detalle (Detail).
RESETRPTTodosNo se utiliza.
PAGEBREAK9-Band/TitleSe imprime la banda Título en una página propia.
9-Band/Group HeaderSe corresponde con el valor de la casilla de verificación Comenzar cada grupo en una página nueva (Start each group on a new page) en el cuadro de diálogo (Data Grouping).
9-Band/Group FooterCoincide con el registro encabezado de Grupo.
9-Band/SummarySe imprime la banda Resumen en una página propia.
9-Band/Detail HeaderSe corresponde con la casilla de verificación Comenzar en una nueva página (Start on a new page) en el cuadro de diálogo Detalle (Detail).
9-Band/Detail FooterCoincide con el registro encabezado de detalle.
COLBREAK9-Band/Group HeaderSe corresponde con el valor de la casilla de verificación Comenzar grupo en nueva columna (Start group on new column) en el cuadro de diálogo (Data Grouping).
9-Band/Group FooterCoincide con el registro encabezado de grupo.
9-Band/Detail HeaderSe corresponde con el valor de la casilla de verificación (Start on a new column) en el cuadro de diálogo (Detail).
9-Band/Detail FooterCoincide con el registro encabezado de la banda detalle.
RESETPAGE9-Band/Group HeaderSe corresponde con el valor de la casilla de verificación Iniciar el número de página en 1 para cada grupo (Reset page number to 1 for each group) en el cuadro de diálogo Agrupar datos (Data Grouping).
9-Band/Group FooterCoincide con el registro encabezado de grupo.
9-Band/Detail HeaderSe corresponde con el valor de la casilla de verificación Iniciar el número de página para cada conjunto de detalle (Reset Page Number to 1 for each Detail Set) en el cuadro de diálogo Detalle (Detail).
9-Band/Detail FooterCoincide con el registro encabezado de detalle.
GENERAL17-PicturesConfiguración de recorte/ escala (Clip/Scale):
0 = Recortar imagen (Clip)
1 = Cambiar la escala de la imagen, conservar la forma (Scale retain shape)
2 = Cambiar la escala de la imagen, rellenar el marco (Scale and fill frame)
SPACING5-Label 0 = Sencillo
1 = 1.5
2 = Doble
8-Field Siempre es 0.
DOUBLE17-PicturesSe corresponde con el valor de la casilla de verificación Centrar imagen (Center picture) en el cuadro de diálogo Propiedades  (Property) del objeto.
1-Report Definition
Report objects
.T. indica el FontCharSet aplicado a este objeto (Ver RESOID)
SWAPHEADERTodosNo se utiliza.
SWAPFOOTERTodosNo se utiliza.
EJECTBEFOR9-Band/SummaryImprimir encabezado de página.
EJECTAFTER9-Band/SummaryImprimir pie de página.
PLAIN1-Report DefinitionSe corresponde con el valor de Agregar solamente Alias no seleccionado (Add non-selected alias only) en el cuadro de diálogo (Expression Builder Options). (Un valor de .T. tiene prioridad sobre el valor de ADDALIAS.)
9-Band.T. = Altura de banda constante
SUMMARYTodosNo se utiliza.
ADDALIAS1-Report DefinitionSe corresponde con el valor de Aliases en el cuadro de diálogo (Expression Builder Options).
.T. si se seleccionó Siempre agregar alias  (Always add alias).
.F. si se seleccionó Nunca agregar alias (Never add alias) (Un valor  .T. en el campo PLAIN tiene preferencia sobre este valor.)
OFFSET6-LineSiempre 1.
7-ShapeRadio utilizado en objetos cuadrados redondeados (los cuadros de diálogo predeterminados utilizados son 12, 16, 24, 32, y 99).
8-Field0 = Alinear a la izquierda
1 = Alinear a la derecha
2 = Alinear al centro
17-PictureIndica archivo o campo general:
0 = Nombre de archivo (almacenado en el campo PICTURE)
1 = Campo General (almacenado en el campo NAME)
2 = Expresión (almacenado en el campo NAME)
TOPMARGINTodosNo se utiliza.
BOTMARGINTodosNo se utiliza.
TOTALTYPE8-Field
18-Variable
Tipos de cálculos:
0 = Nada
1 = Contar
2 = Sumar
3 = Promedio
4 = Mínimo
5 = Máximo
6 = Desviación estándar
7 = Varianza
RESETTOTALCuando TOTALTYPE<>0
8-Field
18-Variable
Determina cuando se reinicia el cálculo:
1 = Al final del informe
2 = Al final de la página
3 = Al final de la columna
5+ = Al final del grupo de datos donde el grupo de datos es (por ejemplo, 6 reinicia el cálculo para el Grupo de datos 1, 7 reinicia el cálculo para el Grupo de datos 2, etc.)
79+ = Al final de la banda de detalle es el número de la banda de detalle (por ejemplo, 80 reinicia el cálculo al conjunto de detalle 1, 81 reinicia el cálculo al conjunto de detalle 2, etc.)
Cuando TOTALTYPE=0
8-Field
Si existe una banda de detalle:
1 = Reiniciar en el grupo/ la banda más interna
Si existen múltiples bandas de detalle:
1 = Reiniciar en el objeto banda de detalle
Cuando TOTALTYPE=0
18-Variable
1 = Reiniciar al final del informe
RESOID1-Report Definition
Report objects
Indica que el FontCharSet aplica para este objeto (o todo el informe).
CURPOS1-Report Definition.T. = Mostrar posición está en ON
.F. = Mostrar posición está en OFF
SUPALWAYS7-ShapeSe corresponde con el valor de Imprimir valores repetidos (Print repeated values) en el cuadro de diálogo (Print when), pero el al revés (observe que este campo y el campo SUPVALCHG se establecen para formas - shapes).
.T. = No
.F. = Si
SUPOVFLOWReport objectsSe corresponde con el valor de (When detail overflows to new page/column) check box en el cuadro de diálogo (Print when).
SUPRCOLReport objectsSe corresponde con el valor de (In first whole band of new page/column) en el cuadro de diálogo (Print when) (0 = sin marcar, 3 = marcado).
SUPGROUPReport objectsSe corresponde con el valor del cuadro desplegable  Imprimir cuando cambia este grupo (When this group changes). Los números son 5+ el número del grupo (por ejemplo, un 6 significa un Data Group 1, un 7 significa un Data Group 2, etc.)
SUPVALCHGReport objectsSe corresponde con el valor del grupo de opciones  Imprimir valores repetidos (Print repeated values) en el cuadro de diálogo (Print when), se incluye por compatibilidad hacia atrás.
.T. = No
.F. = Si
SUPEXPRReport objectsSe corresponde con el valor de Imprimir sólo cuando la expresión es verdadera (Print only when expression is true) en el cuadro de diálogo Imprimir cuando (Print when).
USERTodosDisponible para el uso del desarrollador
Tabla 2. Estructura de la tabla de un informe de VFP 9.0 (FRX)

Conclusión

El Generador de informes de VFP 9.0 Report Writer tiene muchas posibilidades nuevas que ayudan al desarrollador a crear mejores informes. Las características de extensibilidad exponen los trabajos internos del Generador de informes de VFP. Los nuevos entornos de datos reutilizables permiten compartir entornos entre informes. Varios aspectos como objetos y bandas, pueden ser protegidos. Una mejor experiencia de desarrollo se crea a través de la nueva interfaz de usuario. El nuevo diseño de objetos, las características para aplicaciones internacionales, mejoras en la impresión, y las mejoras en la agrupación de datos ofrecen muchas más opciones que las que se disponía antes. Y finalmente, las múltiples bandas de detalle, abre muchas oportunidades nuevas para los informes. Todas estas mejoras juntas brindan la posibilidad de crear informes más complejos que nunca antes.

Biografía

Cathy Pountney es Microsoft Visual FoxPro MVP. Hace 22 años que desarrolla aplicaciones, trece de los cuales como Consultora independiente, especializada en FoxPro. En 2001 tuvo el privilegio de pasar seis meses como contratista en Redmond con el Microsoft Fox Team. Actualmente trabaja para Optimal Solutions desarrollando aplicaciones VFP para escuelas. Cathy ha hablado en numerosas conferencias y grupos de usuarios de FoxPro a lo largo de los EEUU, ha escrito artículos para varias revistas, y su libro, The Visual FoxPro Report Writer: Pushing it to the Limit and Beyond, está disponible en Hentzenwerke Publishing. Puede contactar a Cathy en cathy@frontier2000.com, ver su sitio web en www.frontier2000.com, y ver el sitio web de Optimal Solutions en www.optimalinternet.com.

20 de julio de 2015

Lo nuevo del Generador de Informes en VFP 9.0 - Parte 1

Articulo original: What's New in the Visual FoxPro 9.0 Report Writer
https://msdn.microsoft.com/en-us/library/ms965279.aspx
Autor: Cathy Pountney
Traducido por: Ana María Bisbé York


(Sesión What is new in the Visual FoxPro 9.0 Report Writer? presentada por la autora en la Conferencia DevEssentials Kansas, 2004)

Lea el artículo relacionado, El generador de informes en VFP en acción (Visual FoxPro 9.0 Report Writer In Action: https://msdn.microsoft.com/en-us/library/ms965281.aspx)


Resumen

Aprender sobre las nuevas características del Generador de informes Microsoft Visual FoxPro 9.0, incluyendo los entornos de datos reutilizables, protección de informes, y muchas mejoras en la interfaz de usuario. Aprenderá además, mejoras en el diseño de objetos, mejoras para usuarios internacionales, varias mejoras en la impresión y mejoras en la agrupación de datos. Además, aprenderá sobre dos de los mayores avances del Generador de informes en Visual FoxPro (VFP) 9.0: múltiples bandas de detalles y extensibilidad. Finalmente, aprenderá detalles sobre la estructura de la tabla Visual FoxPro (FRX).

Contenido

  • Introducción
  • Extensibilidad
  • Entorno de datos
  • Protección
  • Mejoras en la interfaz de usuario (UI)
  • Mejoras en el diseño de objetos
  • Características para uso internacional
  • Mejoras en la impresión
  • Mejoras en la agrupación de datos
  • Múltiples Bandas de detalle
  • La tabla FRX
  • Conclusión
  • Biografía

Introducción

Microsoft ha mejorado significativamente el Generador de informes de VFP 9.0, a la vez que reconoce la significativa inversión de los desarrolladores en el informe FRX actual. Sin embargo, el Generador de informes en VFP 9.0 Report Writer es compatible con los informes creados en versiones anteriores de VFP. El generador de informes en VFP 9.0 es una gran mezcla entre lo viejo y lo nuevo.

Extensibilidad

Antes de VFP 9.0, el motor del generador de informes controlaba todo, incluyendo el procesamiento de datos, la posición de los objetos, la generación, la impresión y la vista preliminar. No había forma de entrar en el motor de informes y personalizarlo, como se puede en otras áreas de VFP. Uno de los cambios más significativos en el Generador de informes es su nueva capacidad de extensibilidad. El Diseñador de informes (Report Designer), Motor de informes (Report Engine) y Contenedor preliminar (Preview Container) están expuestos al desarrollador.

Generador de Informes

El Generador de informes (Report Write) en VFP 9.0 incluye una nueva característica en tiempo de diseño llamada Builder Hooks. Varios eventos del Diseñador de informes (Report Designer) están expuestos en un componente Xbase independiente llamado Report Builder, puede ser invocado para ser manipulado. Esta aplicación puede ser utilizada para invocar nuestros propios cuadros de diálogo, aumentar el comportamiento nativo del Diseñador de informes o sobrescribir este comportamiento nativo.

VFP incluye una aplicación extendida en el Generador de Informes, que incluye nuevas características y proporciona una mejor interfaz de usuario para diseño de informes. El Generador de informes es controlado por una nueva variable del sistema, _REPORTBUILDER. Si esta variable está vacía, se muestra el cuadro de diálogo nativo. Para activar el gancho al generador, establezca esta variable a la aplicación correspondiente. Por ejemplo, para utilizar el Generador de informes que viene con VFP 9.0, utilice el siguiente comando:

_REPORTBUILDER = HOME() + "REPORTBUILDER.APP"

Algunas partes de este artículo asumen que está presente el diálogo nativo y la variable de sistema _REPORTBUILDER está vacía. Otros lugares asumen que se encuentra el nuevo cuadro de diálogo y la variable de sistema _REPORTBUILDER tiene valor "REPORTBUILDER.APP." Si no experimenta el comportamiento descrito o no ve los diálogos descritos, puede solucionar el problema, cambiar el valor de _REPORTBUILDER.

Motor de informe (Report Engine)

En el nuevo sistema de salida (Object-Assisted Output), el motor de informe manipula tareas centradas en datos (data-centric chores), como es el movimiento entre los límites y la evaluación de expresiones. Sin embargo, cuando llega el momento de crear la salida, atrasa el trabajo a una nueva clase base llamada ReportListener. La nueva clase genera el contenido del informe en forma más sofisticada, utilizando GDI+, y además ofrece a los usuarios Xbase la posibilidad de interactuar con el proceso de salida. La Figura 1 muestra cómo se ajustan todas las piezas.


Figura 1. Utilice la nueva clase ReportListener para manipular informes.

Para utilizar una clase ReportListener, utilice la cláusula nueva del comando REPORT FORM como se muestra a continuación:

oListener = CREATEOBJECT("ReportListener")
oListener.ListenerType = 1 && Presentación preliminar, o 0 para Imprimir
REPORT FORM <name> <clauses> OBJECT oListener

VFP 9.0 proporciona además una segunda técnica para utilizar una clase ReportListener. Puede establecer el valor para la nueva variable del sistema, _REPORTOUTPUT, al nombre de una aplicación que pueda determinar que clase ReportListener utilizar basada en el tipo de salida que se ha escogido.

Cuando se utiliza (Object-Assisted Output), un informe se procesa utilizando uno de dos modos fundamentales, en dependencia del valor de la propiedad ListenerType. Puede escoger entre estos dos modos print-appropriate (imprimir) y preview-appropriate (presentación preliminar), o page-at-a-time (una página cada vez) y all-pages-at-once (todas las páginas de una vez). En el primer modo, el Listener desencadena un evento OutputPage y prepara cada página, justo como si se enviara cada página a la cola de impresión.

En el segundo modo, el Listener prepara todas las páginas para la generación y las guarda en memoria (caché). Cuando esto finaliza, puede invocar el método OutputPage para preguntar qué página de todas incluidas en la salida por número de página.

Contenedor preliminar (Preview Container)

En VFP 9.0, otra pieza importante en el puzzle de extensibilidad es el Contenedor preliminar. Con este gancho, puede utilizar el nuevo contenedor preliminar que viene con VFP 9.0 o escribir su propio contenedor. El antiguo contenedor preliminar nativo está aún disponible cuando no se está utilizando la nueva salida asistida por objetos.

Una nueva variable de sistema, _REPORTPREVIEW, contiene el nombre de la aplicación que determina qué contenedor preliminar utilizar. De forma predeterminada, esta variable apunta a ReportPreview.app. Esta nueva aplicación contiene un gran número de mejoras sobre el antiguo contenedor preliminar incluyendo: más niveles de zoom, control de la barra de herramientas, control del encabezado, presentación de múltiples páginas, y mejor calidad utilizando GDI+. Las Figuras 2 y 3 muestran las diferencias entre la presentación antigua y la actual.


Figura 2. La salida en el contenedor preliminar antiguo no es muy clara.


Figura 3. El nuevo contenedor preliminar tiene mucha más calidad y opciones más sofisticadas.

Observe la diferencia en calidad entre los contenedores viejo y nuevo. El nuevo contenedor tiene las fuentes mucho más claras que el viejo. Puede comprobarlo utilizando GDI+ para la salida de la información. Observe además, la diferencia en la barra de herramientas anclada. El nuevo estilo de la barra de herramientas tiene opciones nuevas, incluyendo presentación de múltiples páginas.

Salida Tradicional

Un comando nuevo, SET REPORTBEHAVIOR, puede ser utilizado para encender o apagar la salida asistida por objetos. El motor generador de la nueva salida y la nueva superficie Preliminar tienen diferencias significativas entre los estilos de salida antiguo y actual. La alineación, interlineado, y el espaciado es diferente entre GDI y GDI+, con el que podrían haber cambios significativos sobre cómo se vean los informes existentes. Por tanto, se establece de forma predeterminada REPORTBEHAVIOR en 80, lo que apaga la salida asistida por objetos y el informe se procesa como antes de VFP 9.0.

Si desea activar la salida asistida por objetos de forma global, puede cambiar el valor de esta configuración en el cuadro de diálogo Opciones (Options) (mostrado en la Figura 4), o puede escribir el siguiente comando:

SET REPORTBEHAVIOR 90


Figura 4. Utilizar la opción Comportamiento en tiempo de ejecución (Run-time behavior) en el cuadro de diálogo Opciones (Options) para cambiar la configuración de SET REPORTBEHAVIOR.

Cuando REPORTBEHAVIOR se establece en 90, el comando REPORT FORM automáticamente actúa como si pensara que se utiliza la cláusula OBJECT, sin cambios posteriores en su código. VFP utiliza la variable del sistema _REPORTOUTPUT para determinar qué aplicación utilizar para nominar la clase ReportListener apropiada para cada comando REPORT FORM.

Con las nuevas características de extensibilidad en el Generador de informes de VFP 9.0 (Report Writer), es posible tocar el Generador de informes (Report Builder), el Motor de informe (Report Engine), y el área preliminar (Preview surface). Puede activar globalmente las nuevas características o puede activarlas para informes individuales. Puede además dejarlas desactivadas y ejecutar los informes como si estuviera en las versiones anteriores de VFP.

Para más información sobre cómo utilizar la Salida asistida por objetos, vea: El Generador de informes de VFP 9.0 en acción. The VFP 9.0 Report Writer In Action.

Entornos de datos

El Generador de informes de VFP 9.0 (Report Writer) permite ahora compartir Entornos de datos con otros informes. El entorno de datos puede ser guardado como una clase y luego cargado en informes, según la necesidad. Esto brinda nuevas posibilidades para definir y reutilizar entornos en informes con escenarios similares.

Guardar como clase (Save As Class)

Para guardar un Entorno de datos como clase, comience por definir el entorno en el informe, como siempre. Con la ventana Entorno de datos (Data Environment) activa, seleccione la opción Guardar como clase... (Save As Class...) en el menú Archivo (File) (vea Figura 5).

 
Figura 5. Una nueva opción "Guardar como clase..." ("Save As Class...") se muestra en el menú Archivo (File) cuando el Entorno de Datos es la ventana activa.

Después de seleccionar la opción Guardar como clase (Save As Class...) el cuadro de diálogo Guardar como clase (Save As Class) aparece como se muestra en la Figura 6. El botón DataEnvironment del Grupo de opciones Save es el único botón habilitado cuando se guarda un Entorno de datos Data Environment de un informe.


Figura 6. Utilice el cuadro de diálogo Guardar como clase (Save As Class) para declarar el nombre de la nueva clase y la biblioteca de clase para guardar el entorno de datos del informe.

Escriba un nombre para la clase en el cuadro de texto Nombre (Name). Luego, escriba el nombre de la librería de clase en la que desea sea guardada la nueva clase. Si introduce el nombre de una biblioteca de clases que no existe, la nueva biblioteca de clases se crea automáticamente. Puede utilizar el botón de comando elipse (...) para localizar una biblioteca de clases existente. Finalmente puede, opcionalmente, escribir una descripción para la nueva clase.

Cargar un Entorno de datos (DE)

Además de definir manualmente el Entorno de datos para un nuevo informe, VFP 9.0 ofrece la opción de cargar un Entorno de datos de un informe ya existente o de una clase DataEnvironment guardada previamente. La opción Cargar Entorno de datos... (Load Data Environment...) en el menú Informe (Report) (vea Figura 7) permite seleccionar el Entorno de datos a cargar.


Figura 7. Utilizar la opción Load Data Environment... para cargar un Entorno de datos desde un informe existente o una clase DataEnvironment.

Nota La característica Cargar Entorno de datos está disponible sólo a través de los cuadros de diálogo del nuevo ReportBuilder. Debe escribir _REPORTBUILDER = HOME() + "ReportBuilder.app" para poder aprovechar las ventajas de esta característica.

Desde un Informe

Al cargar el Entorno de datos desde otro informe, todo el código y los miembros del Entorno original se copian en el nuevo informe. Esto significa que cualquier cambio que e realice en el Entorno del informe original después de ser copiado no se va a reflejar en el informe creado a partir del informe original.

El cuadro de diálogo Propiedades de informe (Report Properties), aparece, como se muestra en la Figura 8, luego de seleccionar la opción (Load Data Environment...) del menú Informe (Report). Utilice este menú para seleccionar el informe del que desea copiar el entorno al informe actual.

 
Figura 8. Utilice la ficha Entorno de datos (Data Environment) del cuadro de diálogo Propiedades de informe (Report Properties) para seleccionar de qué informe desea copiar el Entorno de datos (Data Environment).

Seleccione el botón Copiar de otro archivo de informe (Copy from another report file) y haga Clic en el botón Seleccionar... (Select...). Esto invoca el cuadro de diálogo Abrir (Open) para que pueda seleccionar a partir de qué informe copiar. Una vez escogido el informe, se muestra un cuadro de diálogo de confirmación (vea Figura 9).


Figura 9. Confirme sus intenciones de copiar un Entorno de datos utilizando este cuadro de diálogo.

VFP 9.0 permite copiar el Entorno de datos de otro informe al informe actual. Sin embargo, VFP 9.0 notifica que sobre-escribirá el Entorno de datos actual y debe hacer Clic en Si (Yes) para continuar. Esto ayuda a recordar que cualquier cosa que se haya definido en el Entorno de datos del informe actual será sobre-escrito. Si hace Clic en No, los cambios no se realizan y el proceso es interrumpido. Cuando hace Clic en Yes, el Entorno de datos es copiado y se notifica con el cuadro de diálogo que se muestra en la Figura 10.


Figura 10. Este cuadro de diálogo confirma que el Entorno de datos ha sido copiado exitosamente al informe actual.

Ya tiene una copia del Entorno de datos. Puede manipularlo según sus necesidades. Sin embargo, recuerde que cualquier cambio que se haga sobre el Entorno de datos del informe original a partir de este momento, no se reflejará en este.

A partir de una clase DataEnvironment

Al cargar un Entorno de datos desde una clase, se agrega código al Entorno de datos del nuevo informe para enlazarlo con la clase DataEnvironment original e instanciarla en tiempo de ejecución. Esto significa que los cambios que pueden realizarse en el futuro sobre la clase DataEnvironment se van a propagar a cualquier informe que emplee esta clase DataEnvironment.

Utilizando el cuadro de diálogo Propiedades de informe (Report Properties), que se muestra en la Figura 8, haga Clic en el botón Enlazar a una clase DE visual (Link to a visual DE class). Luego, haga Clic en el botón Seleccionar... (Select...) para invocar el cuadro de diálogo Abrir (Open) que puede utilizar para seleccionar qué librería de clases y qué clase desea utilizar. Después de seleccionar una clase, se muestra el mismo cuadro de diálogo de confirmación mostrado en la Figura 9. Después de confirmar sus intenciones, el Entorno de Datos es actualizado y se notifica que ha finalizado con el cuadro de diálogo mostrado en la Figura 10.

En este punto, se agrega código a algunos de los métodos del Data Environment. Algunos de los métodos tienen un código tan simple como un único comando DODEFAULT(). La razón para esto es que BindEvents() no funciona si al menos no hay una línea de código.

Código del Entorno de datos

Al cargar un Entorno de Datos a partir de una clase automáticamente agrega código a varios métodos como se muestra y se describe a continuación

Método Init

El siguiente código en el Init es necesario para garantizar que BindEvents() funcione como es esperado.

*---------------------------------------------------------------*
* ESTE CODIGO DE METODO ES AGREGADO POR EL GENERADOR DE INFORME *
*---------------------------------------------------------------*
DODEFAULT()

Método BeforeOpenTables

El siguiente código crea una nueva propiedad en el Data Environment que guarda una referencia de objeto a la clase DataEnvironment que ha sido cargada. Luego, los eventos en este Data Environment se limitan a los eventos de la clase DataEnvironment. Sin embargo, los eventos Init y Destroy no están enlazados. Finalmente, se dispara el evento BeforeOpenTables de la clase DataEnvironment.

*---------------------------------------------------------------*
* ESTE CODIGO DE METODO ES AGREGADO POR EL GENERADOR DE INFORME *
*---------------------------------------------------------------*
LOCAL loMember, laDEEvents[1], liMember, liMembers, loBoundMember
THIS.AddProperty( "BoundDE", NEWOBJECT( "de_insurance", "c:vfp9rwde.vcx" ))
IF VARTYPE( THIS.BoundDE ) = "O" AND UPPER( THIS.BoundDE.BaseClass ) = "DATAENVIRONMENT"
* Enlaza eventos aquí, saltando Init y Destroy.
* El FRX DE y sus miembros solo pueden tener eventos de la clase base,
* por lo que es necesario mucho chequeo de PEMSTATUS:
liMembers = AMEMBERS( laDEEvents, THIS, 3 )
FOR liMember = 1 TO liMembers
IF INLIST( UPPER( laDEEvents[ liMember, 1] ), "INIT", "DESTROY" )
LOOP
ENDIF
IF INLIST( UPPER( laDEEvents[ liMember, 2] ), "EVENT", "METHOD" )
BINDEVENT( THIS, ;
laDEEvents[ liMember, 1], ;
THIS.BoundDE, ;
laDEEvents[ liMember, 1] )
ENDIF
ENDFOR
* Ahora los miembros con verificación apropiada,
* saltándose nuevamente Init y Destroy:
FOR EACH loMember IN THIS.Objects
IF PEMSTATUS( THIS.BoundDE, loMember.Name, 5 ) AND ;
UPPER( PEMSTATUS( THIS.BoundDE, loMember.Name, 3 ) = "OBJECT"
loBoundMember = EVAL( "THIS.BoundDE." + loMember.Name )
IF ( loBoundMember.BaseClass == loMember.BaseClass )
liMembers = AMEMBERS( laDEEvents, loMember, 3 )
FOR liMember = 1 to liMembers
IF INLIST( UPPER( laDEEvents[ liMember, 1] ), "INIT", "DESTROY" )
LOOP
ENDIF
IF INLIST( UPPER( laDEEvents[ liMember, 2] ), "EVENT", "METHOD" )
BINDEVENT( THIS, ;
laDEEvents[ liMember, 1], ;
loBoundMember, ;
laDEEvents[ liMember, 1] )
ENDIF
ENDFOR
ENDIF
ENDIF
ENDFOR
THIS.BoundDE.BeforeOpenTables()
ENDIF

Método AfterCloseTables

El siguiente código en el método AfterCloseTables es necesario para asegurar que el BindEvents() trabaje de la forma esperada.

*---------------------------------------------------------------*
* ESTE CODIGO DE METODO ES AGREGADO POR EL GENERADOR DE INFORME *
*---------------------------------------------------------------*
DODEFAULT()

Método Method

El siguiente código es agregado al método Destroy desenlaza métodos desde el Entorno de datos de este informe a la clase DataEnvironment. El código elimina además la referencia de objeto a la clase DataEnvironment.

*---------------------------------------------------------------*
* ESTE CODIGO DE METODO ES AGREGADO POR EL GENERADOR DE INFORME *
*---------------------------------------------------------------*
LOCAL loMember
UNBIND( THIS )
FOR EACH loMember in THIS.Objects
UNBIND( loMember )
ENDFOR
IF PEMSTATUS( THIS, "BoundDE", 5 ) AND UPPER( PEMSTATUS( THIS, "BoundDE", 3 )) = "PROPERTY"
THIS.BoundDE = NULL
ENDIF

Método Error

El siguiente código en el método Error es necesario para asegurar que el BindEvents() trabaje de la forma esperada.

*---------------------------------------------------------------*
* ESTE CODIGO DE METODO ES AGREGADO POR EL GENERADOR DE INFORME *
*---------------------------------------------------------------*
LPARAMETERS nError, cMethod, nLine
DODEFAULT( nError, cMethod, nLine )

Protección

En VFP 9.0, puede crear protección para uno o más objetos al utilizar el Diseñador de Informes o Diseñador de etiquetas. Esto ofrece la posibilidad de que el usuario pueda modificar un informe, sin permitirle aún hacer determinados cambios.

Configurar las banderas de protección (Setting Protection Flags)

A los objetos se les puede aplicar cinco modos diferentes de protección, los objetos Field tienen una opción de protección adicional. A las bandas se les puede configurar dos modos de protección diferentes. El informe como tal tiene varias opciones de protección.

Nota: La nueva característica Protección está disponible sólo a través de los cuadros de diálogo del nuevo ReportBuilder. Debe escribir _REPORTBUILDER = HOME() + "ReportBuilder.app" para poder aprovechar las ventajas de esta característica.

Proteger un objeto

Para proteger un objeto en el Diseñador de Informes, seleccione el cuadro de diálogo Propiedades (Properties) para el objeto. El cuadro de diálogo Propiedades puede ser invocado desde en menú Informe (Report) después de seleccionar el objeto, desde el menú contextual del objeto, o haciendo doble clic en el objeto. La Figura 11 muestra la ficha Protección (Protection) en el cuadro de diálogo Propiedades para un objeto Field.

 
Figura 11. Utilice la ficha Protección (Protection) del cuadro de diálogo Propiedades (Properties) para establecer los modos de protección a los objetos.

Puede establecer los siguientes modos de protección para los objetos:

  • Marque la casilla de verificación El objeto no puede ser movido ni redimensionado (Object cannot be moved or resized) para evitar que el usuario mueva los objetos a posición diferente en el área de diseño y/o los redimensione.
  • Marque la casilla de verificación El objeto no puede ser modificado (Object cannot be edited) para evitar que el usuario haga cualquier cambio en las propiedades de éste.
  • Marque la casilla de verificación El objeto no puede ser eliminado (Object cannot be deleted) para evitar que el usuario elimine este objeto.
  • Marque la casilla de verificación El objeto no puede ser seleccionado (Object cannot be selected) para evitar que el usuario seleccione este objeto. Cuando se selecciona esta opción, también se seleccionan las opciones de protección: El objeto no puede ser movido ni redimensionado, El objeto no puede ser modificado y El objeto no puede ser eliminado (Object cannot be moved or sized, Object cannot be edited, y Object cannot be deleted.)
  • Marque la casilla de verificación El objeto no está visible en el Diseñador (Object is not visible in Designer) para evitar que este objeto aparezca en el Diseñador de informes en modo protegido. Al seleccionar esta opción, las cuatro opciones restantes también se seleccionan.

La porción Design-time caption de este cuadro de diálogo solo se aplica a los objetos Field. La cadena literal escrita en este cuadro de texto es mostrada en el Diseñador de Informes, en lugar de Expresión (Expression). Esto brinda una oportunidad para mostrar algo que sea familiar al usuario en lugar de una expresión complicada.

Proteger una banda

Para proteger una banda en el Diseñador de Informes, seleccione el cuadro de diálogo Properties para la banda. El cuadro de diálogo Properties puede ser invocado desde la opción Edit Bands... del menú Report, desde el menú contextual de la banda o haciendo doble clic en la barra gris de la banda. La Figura 12 muestra la ficha Protection en el cuadro de diálogo Properties para esa banda.


Figura 12. Utilice la ficha Protección (Protection) del cuadro de diálogo Propiedades de banda (Band Properties) para establecer los modos de protección de la banda.

Puede establecer los siguientes modos de protección para las bandas:

  • Marque la casilla de verificación La banda no puede ser modificada (Band cannot be edited) para hacer inaccesible al usuario el cuadro de diálogo Propiedades de la banda (Band Properties).
  • Marque la casilla de verificación La banda no puede ser redimensionada (Band cannot be resized) para hacer que el usuario no pueda redimensionar la banda.

Proteger un informe

Para establecer protección general al informe, seleccione el cuadro de diálogo Propiedades de informe (Report Properties. Puede llamar este cuadro de diálogo seleccionando Propiedades (Properties) desde el menú Informes (Report) o desde el menú contextual del informe. La Figura 13 muestra la ficha Protección (Protection) en el cuadro de diálogo Propiedades del Informe (Report Properties).


Figura 13. Utilice la ficha Protección (Protection) del cuadro de diálogo Propiedades de Informe para establecer modos generales de protección para el informe.

La parte superior de este cuadro de diálogo permite definir qué fichas del diálogo Propiedades de Informe (Report Properties) están disponibles para el usuario. Para cada selección hecha en esta área, se muestra inhabilitada la correspondiente ficha en el cuadro de diálogo.

La opción Protección (Protection) siempre está seleccionada e inhabilitada. La opción Regla/Rejilla está inhabilitada porque la ficha no puede ser protegida, sin embargo, aparece en el cuadro de diálogo de tal forma que la selección sea consistente con las fichas en el cuadro de diálogo Informes (Report).

La parte inferior de este diálogo permite definir cuáles son las opciones del menú disponibles para el usuario. Para cada selección en esta área, se inhabilita la correspondiente opción del menú.

Respetar banderas de protección

Para invocar la protección durante una sesión del Diseñador de informes o Diseñador de etiquetas, utilice la palabra clave PROTECTED como se muestra en los siguientes ejemplos:

CREATE REPORT MiInforme PROTECTED
MODIFY REPORT MiInforme PROTECTED
CREATE LABEL MiEtiqueta PROTECTED
MODIFY LABEL MiEtiqueta PROTECTED

Si no se utiliza la palabra clave PROTECTED, el Diseñador de Informes trabaja como si no se aplicara protección a los objetos.

Mejoras en la Interfaz de usuario

Se han hecho muchos cambios en la interfaz de usuario para hacer el diseño de informes más fácil e intuitivo. Los menús se han reacondicionado, han cambiado los menús contextuales, y se han agregado nuevas opciones a la barra de herramientas del Diseñador de Informes. El cuadro de diálogo Generador de expresión (Expression Builder) y el cuadro de diálogo Opciones del generador de expresión (Expression Builder Options) tienen un nuevo comportamiento, y se han agregado otras mejoras de de la interfaz de usuario del Generador de informes de VFP 9.0.

Menús

El menú Informes se ha reacondicionado en VFP 9.0 para acomodar nuevas opciones. Además, algunas opciones han sido renombradas para ganar en claridad y otras opciones se repiten en diferentes menús para facilitar el acceso. Las Figuras 14-16 muestran los cambios en los menús nuevos.


Figura 14. La nueva opción "Salvar como clase..." ("Save As Class...") se muestra en el menú Archivo (File).


Figura 15. Se agregó una nueva opción a la barra de herramientas del Diseñador de Informes y se agregaron las líneas horizontales para separar las opciones Grid Lines y Show Position del resto de las opciones.


Figura 16. Se muestran muchos cambios en el menú de informes, incluyendo opciones renombradas, opciones nuevas y agregar la opción Print Preview.

Menús contextuales

Los menús contextuales existentes han sido mejorados con elementos adicionales y más consistencia con los cuadros de diálogos a los que invocan. Otros elementos en el Diseñador de informes que previamente no tenían menús contextuales, ahora sí lo tienen. Las Figuras 17-19 muestran los cambios nuevos.


Figura 17. El menú contextual global tiene nuevas opciones y una opción renombrada.


Figura 18. El nuevo menú contextual para la banda se invoca haciendo Clic derecho en la barra gris de una banda.


Figura 19. El menú contextual para el diseño de objetos se invoca haciendo Clic derecho sobre cualquier objeto del informe.

Barra de herramientas (Toolbar)

La barra de herramientas del Diseñador de informes tiene botones nuevos, como se muestra en la Figura 20.


Figura 20. Se han agregado nuevas opciones para Page Setup y Font Properties en la barra de herramientas del Diseñador de informes.

Cuadro de diálogo Generador de expresiones (Expression Builder)

Se han hecho algunos cambios en el cuadro de diálogo Expresiones de informe (Report Expression). La Figura 21 muestra el cuadro de diálogo Report Expression expandido, lo que permite más espacio para escribir una expresión del informe.


Figura 21. Aprovecha las ventajas del cuadro de edición más grande para "Expresión para el campo en el informe" "Expression for Field on Report:" cuando se introducen expresiones más largas.

Cuando la variable de sistema _REPORTBUILDER está vacía el comportamiento nativo para el cuadro de diálogo Generador de expresión (Expression Builder) es como sigue. Solamente tablas definidas en el Entorno de datos se listan en la lista Campos (Fields). Las tablas abiertas fuera del Entorno de Datos no están disponibles en esta lista.

Cuando la variable de sistema _REPORTBUILDER tiene valor ReportBuilder.app, the el comportamiento para el cuadro de diálogo Generador de expresión (Expression Builder) es algo diferente. Ante todo, es invocado el Generador de expresiones definido en _GETEXPR en lugar del Generador de expresiones nativo. La Figura 22 muestra el cuadro de diálogo Generador de expresión predeterminado.


Figura 22. Utilice el cuadro combinado "Desde la tabla" ("From table") para seleccionar los campos de cualquier tabla abierta.

Este cuadro de diálogo Generador de expresiones tiene un cuadro combinado para seleccionar qué tabla debe ser utilizada al listar los campos en la lista Campos (Fields). Sin embargo, en el cuadro combinado aparecen solamente las tablas que están actualmente en uso. Este es un punto importante a recordar ya que las tablas definidas en el Entorno de datos no se abren automáticamente por el Diseñador de Informes, por tanto, no aparecerán automáticamente en el cuadro combinado.

Esta característica brinda la capacidad de controlar las tablas que están disponibles para el usuario final cuando se permite modificar informes dentro de la aplicación. Puede definir algunas tablas que necesita; pero que no desea que el usuario entre a ellas en el Entorno de datos. Entonces, ya que tiene que abrir específicamente las tablas a las que va a permitir el acceso de los usuarios, puede omitir cualquier tabla que desea mantener fuera de su alcance.

Cuadro de diálogo Opciones del generador de expresiones

El grupo de opciones Alias de campos (Field aliases) se habilita ahora en el cuadro de diálogo Opciones del generador de expresiones como se muestra en la Figura 23. Este grupo de opciones le permite indicar si desea agregar el alias a la expresión de informe cuando se selecciona el campo en el cuadro de diálogo Generador de expresiones.


Figura 23. Utilice el grupo de opciones Field aliases para indicar si las alias de los campos se agregan a los campos seleccionados desde el cuadro de diálogo Generador de expresiones.

Los botones de opciones Agregar Alias siempre (Always add alias) y No agregar nunca Alias (Never add alias) provocan que VFP 9.0 agregue automáticamente el Alias de la tabla, o no agregue el Alias de la tabla, para todos los campos. El comportamiento del botón Add non-selected alias only depende del valor de la variable del sistema _REPORTBUILDER. Si la variable del sistema _REPORTBUILDER está vacía, cualquier campo seleccionado de una tabla que no es InitialSelectedAlias tiene el nombre de la tabla como prefijo. Los campos desde la tabla InitialSelectedAlias no tienen el alias de la tabla como prefijo.

Si la variable del sistema _REPORTBUILDER tiene valor ReportBuilder.app, la opción (Add non-selected alias only) utiliza una lógica diferente, El alias actualmente seleccionada se utiliza en lugar de (InitialSelectedAlias para determinar si se va a poner el prefijo de los alias de tablas a los campos o no.

Además de seleccionar un campo desde el cuadro de diálogo Generador de expresión (Expression Builder) arrastrando un campo desde el Entorno de datos al área de diseño del informe respeta la configuración del grupo de opciones (Field aliases). Además, existe una nueva opción en la ficha Informe (Report) del cuadro de diálogo Opciones (Options) como se muestra en la Figura 24. Esta opción determina que se mantenga la configuración predeterminada de (Field aliases) para todos los informes nuevos.


Figura 24. Utilice la opción del Generador de expresiones (Expression Builder) en la ficha Informes (Reports) del cuadro de diálogo Opciones (Options) para establecer el comportamiento predeterminado para el Generador de expresiones (Expression Builder).

Otras mejoras en la interfaz de usuario

Se han realizado otro grupo de mejoras en la interfaz de usuario que mejoran el diseño de informes.

Cursor del ratón

El cursor del ratón ha cambiado para proporcionar una clave visual de cuando el objeto puede ser redimensionado (vea la Figura 25).


Figura 25. Utilice el nuevo cursor del ratón para saber si un objeto puede ser redimensionado.

Cuadro de diálogo Selección múltiple

En VFP 9.0 existe el cuadro de diálogo Selección múltiple (Multiple Selection) que permite establecer las propiedades Protección (Protection) e Imprimir cuando (Print when) para más de un objeto de diseño a la vez. Permite además cambiar cualquier otra propiedad de Protección a un objeto individual. Para utilizar esta nueva característica, seleccione más de un objeto, y luego haga doble clic en cualquiera de ellos para llamar al cuadro de diálogo Selección múltiple (Multiple Selection) que se muestra en la Figura 26.


Figura 26. Utilice la ficha Selección (Selection) del cuadro de diálogo Selección múltiple (Multiple Selection) para escoger con qué objetos desea trabajar.

Los objetos que fueron seleccionados cuando se ha invocado este cuadro de diálogo se listan en la primera ficha de este cuadro de diálogo. Para trabajar con todos los objetos definidos en un informe, utilice CTRL+A para seleccionarlos todos antes de llamar a este cuadro de diálogo.

La opción Ordenar por (Sort by) permite ordenar la lista de objetos por Tipo (Type) o Ubicación (Location) dentro del informe. El botón Quitar de la lista (Remove from list) elimina los objetos seleccionados en la lista. Hacer Doble-clic en cualquier elemento de la lista, invoca el correspondiente cuadro de diálogo Propiedades (Properties) para el objeto que se ha seleccionado individualmente. La ficha Propiedades (Properties) del cuadro de diálogo Selección múltiple mostrado en la Figura 27, se utiliza para cambiar las propiedades de todos los elementos listados en la ficha Selección (Selection).


Figura 27. Utilice la ficha Propiedades (Properties) del cuadro de diálogo Selección múltiple (Multiple Selection) para cambiar las propiedades Protección (Protection) e Imprimir cuando (Print when) para todos los objetos seleccionados de una vez.

Seleccione Aplicar esta configuración de protección a los objetos seleccionados (Apply these protection settings to the selected objects) para habilitar las opciones de Protección (Protection). Seleccione Aplicar esta condición para los objetos seleccionados una vez guardado (Apply this condition to the selected objects upon saving) para habilitar la opción Imprimir cuando (Print when). Cambie la configuración de Protection y Print when según lo necesite, y luego seleccione Aceptar (OK) para cerrar el cuadro de diálogo y aplicar los cambios a todos los objetos listados en la primera ficha.

Más niveles de Zoom

La ventana Vista previa tiene más niveles de Zoom (vea Figura 28).


Figura 28. Utilice cualquiera de los nuevos niveles de zoom de la vista preliminar de VFP 9.0 para lograr mejor visibilidad.

VFP 9.0 trae muchas mejoras en la interfaz de usuario, incluyendo menús, menús contextuales, y barras de herramientas. Los cambios en el cuadro de diálogo Generador de expresión y Opciones del generador de expresión han incrementado las opciones disponibles al desarrollador. Otras mejoras incluyen el cursor del ratón, el cuadro de diálogo Selección múltiple y más niveles de Zoom.

Mejoras en el diseño de objetos

Se agregaron algunas mejoras al diseño de objetos, incluyendo una opción para controlar caracteres plantilla, un modo Recortar para expresiones de caracteres y posicionamiento relativo y absoluto.

Nota: Para poder aprovechar las ventajas del modo Recortar, debe activar la Salida asistida por objetos, ya sea creando directamente un objeto ReportListener o indirectamente utilizando un comando SET REPORTBEHAVIOR 90.

Caracteres de Plantilla

El cuadro de diálogo Propiedades de campo Field Properties tiene una nueva sección para caracteres de plantilla Template characters, como se muestra en la Figura 29. Las dos opciones disponibles son Cubrir (Overlay) e Intercalar (Interleave). Esto determina el formato en que se utilizan los caracteres especiales.


Figura 29. La opción "Caracteres de Plantilla" determina en que forma se aplican al dato los caracteres de formato especial.

Cuando se utiliza la opción Cubrir (Overlay) los caracteres especiales se tratan como parte del dato y cubre cualquier otro carácter específico en la posición dada. Por ejemplo, cuando la expresión del formato (Format expression) es "999-999," y el dato contiene "123456," el informe muestra "123-56 ." Observe que el "4" se sustituye por un guión en el formato.

Cuando se utiliza la opción Intercalar (Interleave) el carácter especial se inserta entre los caracteres existentes en el dato. Por ejemplo, cuando la expresión de formato es "999-999," y el dato contiene "123456," el informe muestra "123-456." Observe que el guión se inserta entre el "3" y el "4."

Modo Trim (recortar) para expresiones de caracteres

Antes de VFP 9.0, los objetos de tipo campo siempre se recortaban a la palabra más cercana cuando el texto era muy largo. En VFP 9.0, una opción nueva en el cuadro de diálogo Propiedades de campo (Field Properties) permite determinar cómo es recortado el campo (vea Figura 30).


Figura 30. Utilice el modo Recortar para expresiones de caracteres para indicar el método utilizado para recortar textos largos.

Las seis opciones para recortar textos largos son las siguientes:

  • Seleccione Recorte predeterminado (Default trimming) para utilizar el comportamiento predeterminado, que es mismo que la opción Recortar a la palabra más cercana, puntos suspensivos adicionales (Trim to nearest word, append ellipsis). Este comportamiento es similar a las versiones anteriores de VFP, con la excepción de tener puntos suspensivos adicionales.
  • Seleccione Recortar al carácter más cercano (Trim to nearest character) para tener el texto recortado al último carácter escrito que quepa en el área definida.
  • Seleccione Recortar a la palabra más cercana (Trim to nearest word) para tener el texto recortado a la última palabra completa que quepa en el área definida.
  • Seleccione Recortar al carácter más cercano, puntos suspensivos adicionales (Trim to nearest character, append ellipsis) para tener el texto recortado al último carácter que quepa en el área definida una vez que se agrega (...) al texto que imprime.
  • Seleccione Recortar a la palabra más cercana, puntos suspensivos adicionales (Trim to nearest word, append ellipsis) para tener el texto recortado a la última palabra que quepa en el área definida una vez que se agrega (...) al texto que imprime.
  • Seleccione Especificar nombre de archivo (Filespec: Show inner path as ellipsis) para mostrar la carpeta más interna de una ruta larga y el nombre de fichero, con puntos suspensivos adicionales (...) cuando el texto completo no quepa en el área definida.

Tamaño y posición

Otra característica disponible en el diseño de objetos es un mejor control del tamaño y la posición de los objetos, como se muestra en la Figura 31.


Figura 31. Utilice las opciones Tamaño (Size) y Posición (Position) en el cuadro de diálogo Propiedades para controlar la posición relativa y absoluta.

Cuando se agrega un objeto al informe, el valor para las propiedades Desde el borde superior de la página (From page top), Desde el borde izquierdo de la página (From left), Altura (Height) y Ancho (Width) se establecen automáticamente. Es importante observar que la propiedad From page top es relativa al borde superior de la página en el Diseñador de informe, lo que significa que toma en cuenta la altura de cualquier barra gris encima el objeto. Cambiar la propiedad From page top puede mover, sin darse cuenta, el objeto a otra banda.

Posición relativa

La propiedad From page top y la propiedad Height trabajan juntas para determinar si se utiliza posición relativa o absoluta. Cuando la propiedad From page top se establece en un valor que entra dentro del área del Diseñador de informes, y el valor de la propiedad Height es menor o igual a la altura de la banda en la que está localizado el objeto, se utiliza posición relativa. La posición relativa es necesaria para objetos en bandas que no son Encabezado de página (Page Header) y Pie de página (Page Footer).

Posición absoluta

Cuando la propiedad From page top se establece en un valor que entra fuera del área del Diseñador de informes, o el valor de la propiedad Height es mayor que la altura de la banda en la que está localizado el objeto, se utiliza posición absoluta. La posición absoluta significa que el objeto se imprime exactamente en el mismo lugar para cada página.

La posición absoluta puede ser utilizada para crear una marca de agua en el informe. Coloque una imagen gráfica en la banda Encabezado de página (Page Header) y seleccione (Scale contents, retain shape). Cambie la propiedad From page top y la propiedad From left para indicar la esquina superior izquierda de dónde desea que comience la marca de agua. Cambie las propiedades Height y Width para indicar el tamaño total de la marca de agua, asegurándose de no extenderla más allá de los márgenes imprimibles de la impresora.

Características Internacionales

Algunos cambios se han realizado en VFP 9.0 para hacer los informes más funcionales en situaciones internacionales. Específicamente conjuntos de caracteres, lenguaje de scripts, pueden establecerse para fuentes. Unidades (Units) tiene más opciones, así como el comando STRCONV().

FontCharSet

El conjunto de caracteres o lenguaje de scripts, de una fuente, puede ser establecido en el cuadro de diálogo Fuente (Font), como se muestra en la Figura 32. Se puede definir para un objeto específico del informe y además se puede definir la fuente predeterminada para todo el informe.


Figura 32. Utilice el cuadro combinado Script para seleccionar un conjunto de caracteres o lenguaje de script.

Unidades (Units)

El cuadro de diálogo Establecer escala de cuadrícula (Set Grid Scale) tiene tres opciones adicionales en la Escala de regla (Ruler Scale) para permitir especificar la escala en pulgadas o centímetros y apagar la escala. Esto permite un mejor control cuando hay usuarios con varios sistemas predeterminados. La Figura 33 muestra la nueva opción en el cuadro de diálogo Establecer escala de cuadrícula.


Figura 33. Utilice el nuevo cuadro desplegable en el cuadro de diálogo Establecer escala de cuadrícula para un mejor control sobre la regla de escala.

Los mismos cambios que se hicieron sobre el cuadro de diálogo Establecer escala de cuadrícula se hicieron en la ficha Informes del cuadro de diálogo Opciones.

STRCONV()

Otro cambio de VFP 9.0 que ayuda en informes internacionales es el cambio de la función STRCONV(). Ahora se puede utilizar para controlar transformaciones utilizando códigos de páginas y los valores Fontcharset junto con sus IDs locales. La documentación del archivo Ayuda, explica la nueva funcionalidad del comandoSTRCONV().

STRCONV(cExpression, nConversionSetting [,nRegionalIdentifier [,nRegionalIDType]])

nRegionalIDType:
0 - (default) nRegionalIdentifier es LocaleID.
1 - nRegionalIdentifier es código de página.
2 - nRegionalIdentifier es FontCharSet.

Para valores de nConversion iguales a 1, 2, 3, 4, 7, y 8, sólo es soportado nRegionalIdentifier=0

Para diseñar informes en idioma diferente al inglés, las mejoras en FontCharSet, las Unidades, y el comando STRCONV() permiten mayor flexibilidad en el diseño.

Mejoras en la impresión

Algunos comandos existentes y los cuadros de diálogo han sido mejorados para lograr mayor funcionalidad. La función SYS(1037) tiene un nuevo parámetro y devuelve un valor, el comando GetFont() tiene un nuevo estilo, y el comando APrinters() tiene tres columnas.

SYS(1037)

La función SYS(1037) se utiliza para invocar el cuadro de diálogo Configurar impresora Print Setup así como cambiar la impresora predeterminada de VFP. Antes de VFP 9.0, la función SYS(1037) no devolvía un valor significativo. Siempre devolvía una cadena vacía, independientemente de lo que hiciera el usuario. Esto hacía imposible conocer si se había oprimido el botón Cancelar (Cancel).

En VFP 9.0, se agregó un nuevo parámetro a la función SYS(1037) para que devolviera un valor significativo (vea Tabla 1.)

ParámetroDescripciónValor devuelto
SYS(1037)Mismo comportamiento que en versiones anteriores, excepto que ahora devuelve un valor significativo. 0 = Cancelado por el usuario
1 = El Usuario seleccionó Aceptar  OK
SYS(1037,1)Si el área de trabajo actual contiene una estructura que coincida con una estructura FRX y no se ha guardado información de la impresora en el área de trabajo actual, se activa el cuadro de diálogo Configurar página (Page Setup). Si el usuario selecciona Aceptar OK del cuadro de diálogo, VFP escribe los campos EXPR, TAG, y TAG2 en el primer registro del cursor, y luego restablece el cursor al RECNO() anterior.
Si el área actual no contiene la estructura adecuada, no se activa ningún diálogo y devuelve cero.
0 = Cancelado por el usuario o la estructura no es válida
1 = El Usuario seleccionó Aceptar  OK, el FRX se actualiza adecuadamente
 
SYS(1037,2)Si el área de trabajo actual contiene una estructura que coincida con una estructura FRX, la información de impresora predeterminada de VFP se escribe en los campos EXPR, TAG, y TAG2 del primer registro y luego restaura, el cursor al RECNO() anterior.
Si el área actual no contiene la estructura adecuada, no se activa ningún diálogo y devuelve cero.
0 = No se hace ninguna acción, la estructura no es válida
1 = La información de impresora predeterminada de VFP ha sido guardada satisfactoriamente en el FRX
SYS(1037,3)Si el área de trabajo actual contiene una estructura que coincida con una estructura FRX, el Entorno de impresora (Printer Environment) del FRX se guarda como el nueva impresora predeterminada de VFP. Además, sobrescribe, el entorno de impresora en el FRX, en caso de que haya alguna información no válida.
Si el área actual no contiene la estructura adecuada, no se activa ningún diálogo y devuelve cero.
0 = No se hace ninguna acción
1 = Se establece desde el FRX, la información de la Impresora predeterminada de VFP

Tabla 1. Nuevo parámetro y valor devuelto por SYS(1037)

GetFont()

Algunos cambios se hicieron en el comando

Printable Fonts Only

El tercer parámetro de GetFont() tiene un valor nuevo. Al pasar P indica a VFP que sólo muestre las fuentes de impresión para la impresora predeterminada, como se muestra a continuación.

=GetFont(' ', 0, 'P') 

FontCharSet

Como en versiones previas de VFP, se utiliza el cuarto parámetro de GetFont() para identificar el FontCharSet. Sin embargo, se ha hecho un ligero cambio en el significado de pasar 0 o 1 como el cuarto parámetro.

  • Pasar 0 permite que el cuadro desplegable Script, establezca explícitamente "Western script," y devuelva el FontCharSet junto al otro dato.
  • Pasar 1 permite que el cuadro desplegable Script, establezca el valor de la configuración regional de y devuelva el FontCharSet junto al otro dato.

Como en versiones previas, omitir el cuarto parámetro inhabilita el cuadro desplegable Script y no devuelve el FontCharSet como parte del valor devuelto.

APrinters()

Se ha añadido un nuevo parámetro al comando APrinters() para recoger información sobre las impresoras. Si utiliza este segundo parámetro opcional, como se muestra a continuación, provoca que se llene con una columna adicional.

lnPrinters = APrinters(laPrinters, 1) 

Las primeras dos columnas son iguales que en versiones anteriores; Nombre de la impresora (Name of Printer) y Puerto de impresión (Printer Port). Las tres nuevas columnas son (Driver), Comentarios (Comment), y Ubicación (Location).

Al llamar a APrinters() sin el segundo parámetro opcional provoca el mismo comportamiento de versiones anteriores, es decir, se devuelven dos columnas.

Cuadros de diálogos más actuales

El cuadro de diálogo Configuración de impresora (Print Setup) ha sido renombrado como Configuración de página (Page Setup) y se ha modernizado. También se ha modernizado el cuadro de diálogo Impresora (Printer) si se ejecuta bajo Windows 2000 o sistemas operativos posteriores.

Cuadro de diálogo Configurar página (Page Setup)

El cuadro de diálogo (Page Setup), mostrado en la Figura 34, puede ser invocado por algunos de los métodos siguientes:

  • Cuando el diseñador de informes no está activo WONTOP(), seleccione la opción Configurar página (Page Setup) del menú Archivo (File).
  • Cuando el diseñador de informes está activo WONTOP(), seleccione el botón Configurar página (Page Setup) en el cuadro de diálogo Configurar página de informe (Report Page Setup).
  • Utilice SYS(1037).

Figura 34. El nuevo cuadro de diálogo Configurar Página (Page Setup) sustituye al viejo Configurar impresora (Print Setup).

Cuadro de diálogo Imprimir (Print)

El cuadro de diálogo Imprimir (Print), que se muestra en la Figura 35, puede ser invocado por algunos de los métodos siguientes:

  • Seleccione Imprimir (Print) del menú Archivo (File).
  • Utilice la cláusula TO PRINTER PROMPT en comandos, como es REPORT FORM.

Figura 35. El nuevo cuadro de diálogo Imprimir (Print) tiene una apariencia más moderna, cuando se ejecuta bajo Windows 2000 o superior.

... continúa en Lo nuevo del Generador de Informes en VFP 9.0 - Parte 2