Reporte de la Conferencia
DevEssentials 05.06.2004 – Sesión tarde
Por Amby
Bueno, ante mi la difícil tarea
de resumir todo lo que se hablado de temas de informe en VFP 9.0. De
antemano se que no lo voy a lograr, nos va a tocar estudiar la información
que está libre descarga junto con la beta pública de VFP 9.0. Teniendo esto
en cuenta, mi objetivo será entonces comentar los temas que se trataron,
sin pretender explicarlos ni disertar sobre ellos.
¿Qué es lo nuevo en el
Diseñador de informes de VFP 9.0?
(What’s New in the VFP 9.0 Report Writer)
- Cathy Pountney (Microsoft VFP MVP)
Es importante saber que el nuevo
Diseñador de informe soporta el comportamiento de la versión 8.0 y de la
versión 9.0, hay determinados procesos que van a requerir que esté
establecido en la versión 9.0, luego veremos cuáles son y cómo se hace.
Hablemos de las mejoras que trae el Report Writer.
Extensibilidad
Antes de VFP 9.0 el propio Report
Engine controlaba todo el proceso, sin que el desarrollador pudiera influir
en los procesos., incluyendo procesamiento de datos, impresión,
presentación preliminar, etc. La nueva extensibilidad está garantizada
desde el Diseñador de Reportes y el Report Engine.
-
El Generador de informes incluye una nueva característica llamada
Builder Hooks Varios eventos del Diseñador de informes han quedado al
descubierto y un componente Xbase independiente que se llama Report builder
application puede invocarlos y manipularlos.
-
Una nueva aplicación: ReportBuilder.app. Se controla por una nueva
variable de sistema _REPORTBUILDER.:
o
Si _REPORTBUILDER = “” se muestra se
muestra el diálogo nativo.
o
Si _REPORTBUILDER = HOME() +
“REPORTBUILDER.APP” se activa la aplicación que viene con la versión VFP
9.0
-
Report Engine
Actualmente controla los datos (data-centric chores),
esto es el movimiento entre registros y la evaluación de expresiones. Pero,
a la hora de crear la salida, se encarga una nueva clase que se llama
ReportListener. Esta clase en la que se encarga de controlar el
contenido del informe, utilizando ahora GDI+, y además brinda a los
usuarios la posibilidad de interactuar con este proceso de salida.
-
Cláusula OBJECT
en el comando REPORT FORM. Para utilizar la
clase ReportListener hay que utilizar esta cláusula, veamos:
oListener = CREATEOBJECT(“ReportListener”)
oListener.ListenerType = 1 && Preview ó 0 Imprimir
REPORT FORM <nombre> <resto de claúsulas> OBJECT oListener
-
Propiedad ListenerType. Define la forma en que los informes
se van a procesar. Existen dos formas: procesar una página cada vez, o
todas las páginas al mismo tiempo.
-
En el primer caso el Listener desencadena un evento OutputPage
que va a preparar cada página, en el momento en que se desea ver la página
(haciendo Pag Anterior o Sig, o llamando a un número de página
determinado).
-
En el segundo caso, el Listener prepara todas las páginas y cuando
está todo listo, entonces invoca el método OutputPage
Hay dos nuevas variables de
sistemas: _REPORTPREVIEW determina que aplicación se utilizará para
mostrar los resultados. (puede ser reportbuilder.app ) y REPORTOUTPUT
determina cual es la clase ReportListener apropiada para cada clase de
REPORT FORM.
SET REPORTBEHAVIOR
va a activar o no el Object-Asisted Output. Debido a las diferencias
que existen en cuanto a espacios, alineación y otros entre el GDI y el GDI+
es muy posible que prefiera mantener los reportes al estilo VFP 8.0, para
ello escriba:
SET REPORTBEHAVIOR 80
Hasta aquí la verdad es que
parece como que está todo muy enredado, hay que ver los ejemplos de código,
para ver como se genera la cadena de eventos y métodos para obtener los
informes. Una cosa está bien clara, ha cambiado la filosofía del Generador
de informes.
DataEnvironment
Este es un aspecto que también
tiene variaciones.
-
Guardar como clase
– Con la ventana Entorno de datos abierta Menú – Archivo (Guardar como
clase) Save as Class, se muestra el cuadro de diálogo para las
clases.
-
Cargar un Entorno de datos
– En cualquier momento puedo cargar ese entorno de
datos en otro informe, Menú – Informes – Cargar Entorno de datos. Muestra
la ventana propiedades en la ficha Page Layout que presenta dos opciones:
o
Copiar de otro informe – Aparece un
cuadro de diálogo para seleccional el informe que se desea copiar y hay una
advertencia sobre que se va a sobrescribir el Entorno de datos actual.
o
Enlazar con una clase visual
DataEnvironment. Aparece el cuadro de diálogo para seleccionar la clase.
La diferencia importante entre
las dos variantes es que al enlazar con una clase, cualquier cambio que se
haga en la clase en tiempo de ejecución se verá reflejado en los resultados
del informe, pero, en el caso contrario se copian físicamente todos los
elementos que conforman la estructura del Entorno de datos del informe de
origen. Si se modifica ese informe no se verán los cambios en el informe en
el que se copió.
Protección
A este tema ya me referí en el informe de ayer, se puede establecer
protección, a nivel de objetos, bandas y reporte como tal. Para poder
acceder a esta facilidad hay que estar utilizando la aplicación
ReportBuilder.app. Recordemos que debemos utilizar la cláusula PROTECTED
en los comandos CREATE y MODIFY REPORT para ver los efectos.
Interfaz de usuarios (UI)
Menú:
Archivos - Nueva opción Save as class
Informes
–
Cambio de orden de las opciones para que queden agrupadas de forma más
lógica.
-
Nueva opción Load DataEnvironment
Barra de herramientas del
Diseñador: Hay dos nuevos botones:
Page Layout, para poder definirlo desde el
propio informe y no tener que ir a Menú – Archivo.
Font propierties – Se activa si hay uno o
más elementos del informe seleccionados. Para definir las propiedades de
la Fuente directamente sin ir a navegar por los menús.
Bandas
– Clic derecho, nueva opción Optional bands
Generador de expresiones.
En las versiones anteriores se muestran en la lista todos los campos de
todas las tablas, vistas y cursores activos, lo que complica en muchas
ocasiones su navegación. Ahora solo se mostrarán los campos de las alias
actualmente abiertas, independientemente de todo lo que esté definido en el
DataEnvironment. Pero, como hay gustos de todos tipos en el comando
Opciones se puede definir como el desarrollador quiere que le aparezca
la lista de campos, hay 3 opciones:
o
Agregar siempre las alias (todas)
o
Agregar las no seleccionadas
o
No agregar ningún alias
Selección múltiple:
Pues si, ya existe selección múltiple en el Diseñador de informes ¡¡ Al
fin!! Pues se muestra un nuevo cuadro de diálogo Selección múltiple
aquí las opciones que se pueden configurar con las relativas a la
protección y otras como el Print went (Imprimir cuando…), para mí esto
representa un ahorro considerable de tiempo, pues muchas veces hay que
repetir la misma condición en el Print went y no teníamos forma de hacerlo
de una vez. De todas formas sigue siendo incompleto en cuanto a otras
propiedades que sería útil poder configurar con una selección múltiple como
la fuente, altura, etc. Para acceder a la selección múltiple, hay que
seleccionar los elementos, clic derecho y Propiedades.
Ventana presentación
preliminar.
-
Aumento de las posibilidades de Zoom hasta 500 %
Soporte para escritura
internacional Aquí hay que mirar la
propiedad FontCharSet y la función STRCONV(), - podemos definir el tipo de
caracteres en que vamos a mostrar la información, en dependencia del idioma
hay variaciones en cuanto a las posibilidades de los scripts.
Menú – Opciones – Informes:
Varía la escala de la regla, que se aplica para aumentar posibilidades de
nuevas medidas (ml)
En la impresión:
Sys(1037) – permite saber si el
usuario canceló o no la impresión, dejando resuelta de si hubo error del
informe o es que el usuario canceló, se puede hacer seguimiento de errores
controlando el valor devuelto por esta función.
Además hay que ver: GetFonts(),
APrinters() y los diálogos Page setup y Print
Mejoras en la agrupación de
datos:
1.- Aumenta la cantidad,
2.- Con múltiples columnas, y
dirección de impresión horizontal (de izquierda a derecha), se producía un
error cuando cambiaba de grupo. Ha sido reparado.
Bandas multidetalles
De este tema, también he
comentado ya, solo expongo algunos aspectos en los que Cathy Pountney llamó
la atención. El trabajo multibandas nos ofrece nuevas posibilidades; pero
nos exige ser mucho más cuidadosos, porque ahora en cada banda no estará la
tabla padre sino una de las hijas, y no hay que olvidar en el Cuadro de
diálogo Propiedades de la banda de detalle (Detail band propierties)
completar el dato Expresión del alias (Target alias expresión) con
el nombre del alias, ¡¡¡ entre comillas !!! porque en caso contrario toma
el area padre y el resultado es bastante impredecible. En caso de estar
trabajando con una sola banda, pues no pasa nada si la dejamos en blanco,
toma la tabla padre que será justo lo que deseamos.
Nueva cláusula SUMMARY –
Esta cláusula nos permite obtener solo los encabezados y pie de cada banda
sin mostrar el contenido de los detalles, es una buena opción, porque ahora
el usuario podrá decidir si quiere la información compactada o detallada.
Las variables calculadas en el
informe adquieren una nueva dimensión, Reset based on, en la ficha
Variables de la ventana Propiedades indica que se deben procesar los
registros de la tabla hija y no se limpia hasta que no termine el informe,
lo que permite realizar cálculos y combinaciones entre las bandas
utilizando valores calculados de unas en otras.
Ejemplo:
Para poner los totales al inicio,
en el encabezado de banda..
Hacer 2 bandas con idem alias, el
primera banda se calcula el total y se el valor calculado en el encabezado.
Pero esta banda no tiene más nada, no hay nada en el detalle ni el pie de
banda.
Entonces, el la segunda banda
están los datos en el detalle; lo importante es que VFP no está apuntando
al último registro de esa tabla, por haber hecho SUM, COUNT, o la operación
que sea, no, el puntero de la tabla al llegar a la segunda banda apunta al
registro que corresponde por la relación padre-hija que existe con la tabla
padre que es quien rige el informe.
Pues hasta aquí lo que explicó
Cathy Pountney. Habrá varios artículos en próximas fechas que estarán en
las páginas de MSDN, estaremos muy atentos.
Nada, un café…. O dos…. Se está
llenando el local, así que lo que viene, promete mucho.
Extender el sistema de
informes de VFP 9.0, Parte 1: Tiempo de diseño -
Extending the VFP 9.0 Reporting System, Part I: Design-Time Doug
Hennig - Microsoft Most Valuable Professional (MVP) y Certified
Professional (MCP).
Entre las nuevas y mejoradas
características del diseñador de informes está la posibilidad de extender
el Diseñador de informes, hacerlo más poderoso y flexible, para el
desarrollador e incluso para el usuario final.
La nueva variable de sistema _REPORTBUILDER
apunta a una aplicación XBase (en este caso reportbiulder.app) que recibe
la notificación sobre los eventos desde el Diseñador de informes. Cuando
ocurre un evento en tiempo de diseño y _REPORTBUILDER apunta a una
aplicación existente, el Diseñador de informes crea una sesión privada de
datos y abre una copia del archivo FRX actual que es editado en esa sesión
de datos, luego llama a reportbuilder.app
Cuando ocurre un evento, el
Diseñador de informes pasa los siguientes parámetros a la aplicación
generadora de informes (report builder aplication):
|
Parámetro |
Tipo |
Descripción |
|
ReturnFlags
|
N |
Pasado por referencia con
valor inicial de -1. Se usa para devolver
valores al Diseñador de informes |
|
EventType |
N |
Una representación (integer)
del evento que ocurrió |
|
CommandClauses |
O |
Un objeto Empty cuyas
propiedades indicanque claúsulas se utilizaron en el comando
CREATE/MODIFY REPORT |
|
DesignerSessionID |
N |
El ID de la sesión de datos
del Diseñador de informes |
Los posibles valores para
ReturnFlags son:
FRX_REPBLDR_HANDLE_EVENT – Viene
siendo como un NODEFAULT. No se ejecuta el evento que haría normalmente el
Diseñador de informes.
FRX_REPBLDR_RELOAD_CHANGES -
El reportbuilder.app hace los cambios en el cursor FRX para que el
Diseñador de informes pueda cambiarlos internamente a su copia de
FRX.
Eventype
puede traer muchos valores en dependencia de qué elemento de informe sea el
que desencadenó el evento:
Ej: FRX_BLDR_EVENT_OBJECTCHANGE
– se ha movido un objeto o banda. En cada evento, además está definido si
se puede eliminar o no, en este caso sí.
Vimos las propiedades de
CommandClauses: ej:
Protected
– Devuelve .T. si se especificó la cláusula PROTECTED en el comando
MODIFY REPORT/LABEL. De la misma forma existen: NoEnvironment,
NoOverwrite, NoWait y otras muchas.
ReportBiulder.App
– es una aplicación que proporciona el framework para manipular los eventos
en tiempo de diseño, además proporciona un grupo de nuevas y atractivas
funcionalidades, cuadros de diálogo que sustituyen al Diseñador de informes
actual. Es personalizable a través del Cuadro de diálogo Report builder
Options, que se muestra luego de hacer:
DO (_REPORTBUILDER
Se pueden crear manipuladores de
eventos (Report Event Handler) e integrarlos al nativo. Doug Henning
ha escrito sobre cómo sería este proceso de integración, las propiedades y
eventos sobre las que hay que trabajar para ello.
Procesamiento de eventos
Explicó lo que sucede cuando
ocurre y evento y es llamada la aplicación ReportBuilder.APP, se ejecutan
los registros filtrados previamente, trata de encontrar el controlador para
el evento, si encuentra un controlador, lo instancia y llama al método
Execute, en caso contrario termina.
Event Object
– Es un objeto de evento pasado por el ReportBuilder.APP al método
HasHandled.
A continuación los ejemplos
prácticos de cómo funciona este proceso. Comentó como evitar el acceso de
los usuarios al entorno de datos, y lo hizo a través del SFEventKiller
que es un controlador de eventos sencillo, que indica que hay que
ejecutar el evento personalizado y no el nativo.
Hay que recordar que lo más
importante es revisar toda la información que aparece en la beta pública.
Con todo esto, y resulta que aún
hay más !!, qué va, me tomo un café para estar bien despejadita para lo que
viene.
Extender el sistema de
informes de VFP 9.0, Parte 2: Tiempo de ejecución -
Extending the VFP 9.0 Reporting System, Part II: Run-Time Doug
Hennig - Microsoft Most Valuable Professional (MVP) y Certified
Professional (MCP).
Pues, lo dicho, además de las
mejoras en tiempo de diseño, que ya fueron debatidas en la sesión anterior,
las sorpresas con el Diseñador de informes continúan y en su nueva versión
9.0 aumenta las posibilidades también en tiempo de ejecución.
Lo primero que hemos es de saber,
es que la Arquitectura ha cambiado, antes de VFP 9.0 el motor del
informe era monolítico, manipulaba todo, a excepción de las UDFs,
expresiones en las OnEntry y OnExit de las bandas, etc. No se podía
interactuar con el informe en tiempo de ejecución.
Se resume en este esquema.
La nueva arquitectura divide las
responsabilidades entre el motor (report engine) el que ahora solo
se ocupa de los datos y la posición de los elementos del informe y un
objeto nuevo conocido por Report listener, el que se encarga de todo
lo demás. Debido a que los report listeners son clases, podremos
interactuar con el proceso de creación de informes de forma que antes ni
soñábamos.
Veamos el esquema
Existen dos modelos en los que se
ejecuta la salida del informe:
-
Una página cada vez (Page-at-a-time) organiza todas las
páginas y luego lo envía. Es el caso de imprimir.
-
Todas las páginas a la vez (all-pages-at-once) Ordena todo el
informe y guarda la información de cada página en memoria. La salida de
cada página depende de la demanda, ej, si se desea ver página anterior o
posterior. Es utilizado típicamente en la vista preliminar. Veamos:
1.- Toma los objetos
ReportListener y ReportPreview
2.- Ejecuta el informe y genera
todas las páginas
3.- Controla el paso al
Previewer con el número de página requerido.
Nueva sintaxis para informes.
Para poder obtener el nuevo
estilo de comportamiento en los informes, hay que utilizar la claúsula
OBJECT en el comando REPORT. Un report listener es un objeto que
proporciona el nuevo estilo de comportamiento. Está basado en una clase
base nueva de VFP 9.0 ReportListener.
loListener = createobject('MyReportListener')
report form
MyReport object loListener
ReportListener
Esta clase base permite, no solo
el comportamiento nativo de imprimir o mostrar preliminarmente sino que
extensible a subclase aumentando mucho sus ventajas.
Si analizamos todas sus
propiedades vemos las posibilidades que brinda:
AllowModelMessage (L) – permite mostrar
mensajes que van mostrando el proceso de ejecución del informe
CurrentDataSession (N) – ID de la sesión
de datos actual
DynamicLineHeight (L) – para utilizar el
GDI+, lo que implica que el espaciado entre líneas varía según el font
La propiedad CommandClauses
contiene una referencia a un objeto vacío, cuyas propiedades
representan varias cláusulas del comando REPORT, y otro grupo de cosas más.
Ejemplos:
DE_Name – Nombre del objeto DataEnvironment
del informe
lsReport (L) - .T. si es un informe
(report), .F. si una etiqueta (label)
NoEject, Nodialog, NoConsole, Plain, Preview, Prompt
– si están en las cláusulas.
Eventos -
Los eventos se separan por tipo de aspecto del report,
de esta forma hay :
Eventos del informe – LoadReport,
UnloadReport, BeforeReport, AfterReport y OnPreviewClose
Eventos de las bandas – BeforeBand,
AfterBand
Eventos de Objetos –
EvaluateContents(tnFRXRecno, toObjProperties)
AdjustObjectSize(tnFRXRecno, toObjProperties)
Render(tnFRXRecno, tnLeft, tnTop, tnWidth, tnHeight,
tnObjectContinuationType, tcContentsToBeRendered, tnGDIPlusImage):
Métodos
CancelReport, OutputPage,
DoStatus … y otros
Registrar Listeners
ReportOutPut.APP utiliza una
tabla de registros para definir qué listeners debe conocer. La tabla nativa
es OutputConfig.DBF sus campos son: OBJTYPE, OBJCODE, OBJNAME,
OBJVALUE, OBJINFO
Con todas estas clases,
propiedades, métodos y eventos se puede accionar en tiempo de ejecución.
A partir de este momento se
sucedieron ejemplos del funcionamiento de esta nueva arquitectura:
- cómo agregar marca de agua en
tiempo de ejecución
- alternar colores para las
líneas de detalle
- concatenar informes
- colocar gráficos
Pues ya está, esto es lo
fundamental que se expuso, ahora… ¡¡ a estudiar ¡! Gracias a Cathy
Pountney y Doug henning, han estado geniales.
Saludos,
Ana
www.amby.net
|