Sei sulla pagina 1di 11

El Rinconcito de Delphi

TQuickReport
Nstor Freire
nestorfreire@wanadoo.es
El presente artculo ha sido cedido para su publicacin
en El Rinconcito de Delphi. Es ilegal cualquier actuacin
que vulnere los derechos del autor.
El Rinconcito de Delphi Nstor Freire
1
TQuickReport

Manejo de datos y expresiones

El uso ms normal de TQuickReport es poner unas bandas, asignar una base de datos y
previsualizar. Con este artculo intentar explicar otras funciones de este generador de informes,
que bien usado puede hacer maravillas y sin escribir ni una sola lnea de cdigo (aunque esto no
siempre es posible). Para ello, usar QuickReport 3.0.5, Delphi 5 y los controles que vienen en la
instalacin completa de la versin Profesional del mismo. En otras versiones puede que no estn
incluidos algunos de los controles de los que hablar o el cdigo no sea completamente compatible.
De todos modos, en la mayora de los casos no es un problema insalvable.

Exportacin de informes

Exportar es muy sencillo. Hay cuatro tipos de exportacin, que varan segn el formato deseado.
stos son:

Extensin Descripcin Control
.QRP Exportacin estndar. Es el nico que permite importar Ninguno
.TXT Archivo de texto. El resultado es muy parecido a lo que se ve en pantalla TQRTextFilter
.CSV Archivo de Excel. Resultado un poco catico, pero se puede arreglar. TQRCSVFilter
.HTML No genera saltos ni nada parecido, y necesita algunos retoques, pero
puede ser muy til para publicar los listados en Internet.
TQRHTMLFilter

La extensin .QRP es la que ms espacio necesita, pero es la nica que permite cargar informes.
Este formato siempre est disponible, sin controles aparte.
En realidad, hay mas controles de los que nombro, pero sos estn en la versin Enterprise de
Delphi 5, y se usan igual que los que he mencionado, por lo que no hablare de ellos.
Para dar una idea de cunto puede ocupar un informe, he creado uno con 11 hojas, tipo
Master/Detail, controles de pie de pgina y ttulo. Lo he guardado en los cuatro formatos, y stos
son los resultados:

Extensin Tamao
.QRP 512 Kb
.TXT 22 Kb
.CSV 30 Kb
.HTML 74 Kb

Llama la atencin el exagerado tamao de .QRP, pero (supongo) se debe a que no guarda los
datos, como las otras extensiones, sino que, adems, guarda las bandas, etiquetas, propiedades, etc.
sin necesidad de ninguna lectura posterior a las bases de datos.
Y ahora, por fin, explico cmo se puede hacer. Se coge el control, o los controles, de los antes
mencionados, que se desee y se deja caer sobre el mismo formulario donde se encuentra el
Q.Report. Con esto ya aparecer la opcin de guardar el informe con la extensin correspondiente
al pulsar el botn Guardar (slo valido en tiempo de ejecucin).

Mostrar un solo registro/ Mostrar ciertos registros

Adems de la posibilidad del Q. Report de mostrar toda la base de datos, hay veces que interesan
tan solo algunos datos almacenados. En estos casos hay tres sistemas: Crear todas las etiquetas
(TQRLabel) necesarias y rellenarlas a mano, crear un informe de toda la tabla, de forma que cada
registro ocupe una hoja entera e imprimir nicamente la hoja que interesa, o usar un componente
El Rinconcito de Delphi Nstor Freire
2
TQuery. Este componente se utiliza para ejecutar instrucciones de SQL, y de hecho, eso me
propongo, aunque no es exactamente del tema de Q.Report.
Para empezar creamos un componente TQuery en el mismo formulario donde est el informe.
Asignamos su propiedad DatabaseName a la tabla correspondiente, y en el Q.Report, cambiamos la
propiedad DataSet al TQuery que acabamos de hacer. Despus creamos una variable del tipo que
vallamos a seleccionar en la impresin (si queremos seleccionar un String, la creamos de tipo
String). Esto se hace dentro de Parameters, en el Query. Despus en la propiedad SQL escribimos
algo as:

select * from BaseDatos where BaseDatos.Campo =: NombreParametro

Esto le indica que debe seleccionar todos los campos de la BaseDatos mientras que el campo
Campo (Que imaginacin! :-) ) sea igual al parmetro que hemos creado antes (por eso el
parmetro debe ser del mismo tipo que el dato que se busca). Para poner en funcionamiento todo
esto escribimos en nuestra unidad:

Query.Active := False;
Query.ParamByName('NombreParametro').AsString := TextoBuscado;
Query.Active := True;
If Query.IsEmpty then ShowMessage (No encontrado);

Con este cdigo seleccionamos los registros en los que el Campo sea igual a TextoBuscado. Aqu
hay que darse cuenta de dos cosas: 1) Primero se cierra el Query, se asigna la bsqueda y se abre.
Luego se comprueba el resultado. 2) Aqu se usa AsString porque buscamos un String, pero hay
mas tipos. Pongo a continuacin los que se pueden usar:

Tipo de datos Correspondencia en Delphi Funcin correspondiente
BCD Currency AsBCD
Blob String AsBlob
Boolean Boolean AsBoolean
Currency Double AsCurrency
Date TDateTime AsDate
DateTime TDateTime AsDateTime
Float Double AsFloat
Integer Integer AsInteger
Memo String AsMemo

Ahora digo que diferencia hay entre mostrar un registro slo o unos pocos: ninguna. Si en el
campo slo hay un dato que coincida con el que buscamos, nada ms coge este. Entonces si
buscamos el DNI, seleccionaremos uno, sin posibilidad de que se repita. Si buscamos un nombre,
puede ocurrir que haya ms de uno, entonces estaremos seleccionando unos pocos registros.
Y slo queda mostrar esto en el informe. Recordar que le habamos indicado al Q.Report que
cogiera los datos del Query. Tambin recordar que le hemos dicho al Query que seleccionara
nicamente los registros que coincidan. Entonces el informe slo mostrar esos, ya que no hay
ningn otro registro en el sitio que busca. Esto se puede ampliar mas, pero entonces tendra que
escribir el artculo sobre SQL o InterBase. Manejando bien este tema, se pueden hacer muchas
cosas; yo creo que merece la pena.

Informes Master/Detail

Este tipo de informes es muy importante, ya que es una relacin entre dos tablas. Para explicarlo
bien pondr un ejemplo: Tengo en una tabla los datos de las filiales de una empresa. En los datos
El Rinconcito de Delphi Nstor Freire
3
est el presupuesto, nombre, direccin, etc., y un campo con un nmero nico para cada empresa
(Es importante que sea nico). En otra base de datos tengo la lista de empleados con el DNI, sueldo,
datos, y un campo que tiene el cdigo de la empresa en la que trabajan. Un informe Master/Detail
creara una lista de las empresas, y entre cada nombre, intercalara todos los trabajadores de esa
empresa, en vez de listarlos aparte. Estos informes son tiles para dar datos de dos bases distintas
pero con una relacin entre ellas.
Antes de empezar aclaro que voy a llamar a la base de datos principal Maestro y a la secundaria
Detalles.
Debemos tener dos bases de datos, la Maestra debe tener un campo en la que no se repita ningn
valor. Este campo ser el que relacione. La base Detalles debe tener un campo (con cualquier
nombre) del mismo tipo que la base anterior. Si es distinto no sirve. Aqu s se pueden repetir, y, de
hecho, es bastante normal. Los dos campos que se deben relacionar deben estar en un ndice.
Entro en Delphi. Creamos en un formulario dos componentes de tipo TTable o TQuery, y uno de
tipo TDataSource. A los primeros les llamo Uno y Dos, y al segundo Source. A Uno lo conecto con
la tabla Maestra, y a Dos con Detalles. Despus a Source asigno a la propiedad DataSet el valor
Uno (que contiene a Maestra). Luego cambiamos la propiedad MasterSource de Dos a Source. Para
terminar abrimos el dilogo de la propiedad MasterFields. En la lista Detail Fields aparecen los
campos de Detalles que tienen ndice y lo mismo ocurre en la lista Master Fields, pero con los
campos de Maestro en el ndice. Seleccionamos en cada lista el campo que vamos a unir, pulsamos
el botn Add, y ya hemos terminado aqu.
Empezamos con Q.Report. Asignamos su propiedad DataSet a Uno. Creamos bandas, ponemos
controles y cuando ya est esa parte terminada empezamos con la segunda tabla. Creamos un
TQRSubDetail, asignamos DataSet a Dos y Master a QuickReport. En esa banda situamos los
controles que muestran los datos de la segunda tabla. Y ya est. Si hay ms de una banda, puede dar
problemas. Para solucionarlos cambie la propiedad LinkBand de TQRSubDetail para que aparezca
el nombre de la banda a la que debe complementar.
Para terminar, resumir todo y ver que fcil es. Creo tres controles, dos de ellos leen los datos, el
otro los conecta. Asigno las propiedades para que sepan que campo les une. Creo el informe, y
aado una banda especial para este tipo de informes. Le aclaro a la banda quin es el jefe y, en caso
de problemas le asigno un lder al que deben seguir :-).
Slo me queda decir que en el nico sitio que se muestran los datos de Dos es en la banda
TQRSubDetail. En caso de que haya ms de una banda de tipo Detail, se debe indicar, como ya he
dicho, a cul debe estar unida.

Expresiones

Dentro de QuickReport hay un sub-lenguaje (digo lo de sub- por su reducido tamao) que puede
llegar a ser bastante complejo y est formado por 21 funciones, 3 variables locales, 3 variables de
entorno y todos los campos de una base de datos. A primera vista no parece mucho, pero se puede
usar en varios de los componentes de Q.Report (TQRExpr, TQRExprMemo y TQRGroup) y tiene
muchas opciones. Cualquier dato que pida una funcin puede sustituirse por otra funcin, e incluso
tiene estructura de tipo If.
El fallo ms importante que tiene, es que si no reconoce algo, puede dar un error en una librera.
Adems, no se pueden insertar espacios antes de los nombres, o no los reconoce. Y lo mejor es que
si da fallos, suele indicar donde los da y porqu. Si no hay, devuelve el valor tras efectuar al
operaciones y funciones indicadas.
Algunos datos generales: Las cadenas literales se escriben con comillas simples ( ), los tipos
que se manejan son numricos (con o sin decimales), carcter y booleanos, las maysculas y
minsculas no se diferencian (excepto en los literales), la nica estructura disponible es If, se
pueden crear y usar cualquier nmero de variables, tanto locales como globales. A dichas variables
El Rinconcito de Delphi Nstor Freire
4
no se les pueden asignar valores, pero al crearlas dan la opcin de asignarlas una expresin,
utilizando este lenguaje. Cuando se lea su valor, utilizar la expresin para proporcionarlo.
Las lneas no se separan con ( ; ). Se pueden leer datos de las tablas, de variables y los resultados
de las funciones. En cualquier momento se puede sustituir valores por variables o funciones,
siempre que sean del tipo requerido. Adems de pueden anidar las funciones y comandos. En textos
y ejemplos no dir nada ni pondr ejemplos de esto, excepto en el apartado correspondiente, sin embargo,
se puede hacer siempre. El nmero mximo de decimales que admite es 13. En caso de que haya ms, se
ignoran.
Quiero mostrar antes de empezar dos imgenes para que se vean algunas posibilidades de esto.
Presento primero la imagen de resultado, y despus la ventana de Delphi.



FIGURA 1 (RESULTADO)



El Rinconcito de Delphi Nstor Freire
5
FIGURA 2 (IMAGEN DELPHI)

Lo que est escrito en los TQRExpr es:

ExpNombre: Uno.Num + ' : ' + Uno.Nombre
ExpTelefono: 'Telfono : ' + Uno.Tlf
ExpPed1: Dos.Ped1 + ' (' + Dos.Numero + ')'
ExpPed2: Dos.Ped2 + ' (' + Dos.Numero + ')'

Ms adelante veremos qu significa. Por ahora comento las funciones existentes:

Funciones

IF (Exp,Val1,Val2)
Evala la expresin booleana Exp. Si es cierta ejecuta Val1, si no, ejecuta Val2.

IF(PAGENUMBER = 1,Pag1 = TRUE,Pag1 = FALSE)
Si El nmero de pgina es 1, asigna el valor True a Pag1, si no, asigna el valor False a Pag1

STR (Val)
Convierte el nmero Val a String

NUM = STR(1234)
Asigna a la variable NUM (de tipo String) el valor 1234

UPPER(VAL)
Convierte Val a maysculas. No tiene problemas con acentos, s, espacios, comas...

UPPER(HolA)
Convierte a maysculas la cadena HOLA.

El Rinconcito de Delphi Nstor Freire
6

LOWER(Val)
Convierte Val a minsculas. Tiene las mismas limitaciones que la funcin Upper

LOWER(HOlA)
Transforma HOLA en hola

PRETTY(Val)
Modifica la cadena Val poniendo la primera letra en mayscula y las otras en minsculas

PRETTY(buenOS Dias)
Devuelve Buenos dias

TIME()
Proporciona la hora actual del sistema (HH:MM:SS) en formato String

DATE()
Retorna la fecha del sistema (DD/MM/AA) en formato String

COPY(Text,Val1,Val2)
Funciona igual que la funcin de Delphi con el mismo nombre. Se usa para coger unos pocos
caracteres de la cadena Text. Empieza en el carcter Val1 (incluido) y coge Val2 caracteres.

COPY('Hola que tal ests',6,7)
Devuelve que tal

MAX (Val)
Devuelve el valor mximo que haya tomado la variable Val.

MIN(VAL)
Establece el valor mnimo que haya tomado Val (generalmente 0 o 1, pero puede cambiar)

AVERAGE(Val)
Calcula la media de los valores que haya tomado la variable Val. Usa 1 decimal.

TRUE, FALSE
Valores booleanos. No tienen parmetros. No devuelven ningn valor. Se usan parecido a Delphi

INT(Val)
Devuelve el valor entero de la variable Val. Se usa igual que TRUNC(Valor). El carcter decimal
es el punto ( . ).

INT(8.97)
Devuelve 8

FRAC(Val)
Devuelve el valor fraccionario del numrico Val. El carcter decimal es el punto ( . ). Puede dar
algunos errores (ver los ejemplos)

FRAC(8.9)
Devuelve 0,9

FRAC(8.95)
El Rinconcito de Delphi Nstor Freire
7
Devuelve 0,949999999999999 (Quiz podramos solucionar esto en Delphi usando una variable
Currency, pero aqu slo existe la variable Integer, vlida para todos
los nmeros)


SQRT(Val)
Calcula la raz cuadrada del nmero Val. Puede usar 13 decimales.

SQRT (6)
Devuelve 2,44948974278318

DIV(Val1,Val2)
Realiza la divisin entera (sin decimales) de Val1 entre Val2. No redondea.

DIV(14,3)
Devuelve 4

TYPEOF(Expr)
Evala la expresion (o variable) Expr y devuelve el tipo de datos (STRING, INTEGER,
BOOLEAN)

FORMATNUMERIC(Num,Mask)
Formatea el nmero Num con un string como mscara (ver la ayuda de la VCL para ms
informacin, buscar FormatFloat)


Tambin se usan muchos operadores matemticos. La mayora tambin estn presentes en Delphi
y funcionan muy parecido. Sin embargo, tiene una diferencia importante: el ( = ) se utiliza
exclusivamente como comparador. Las nicas asignaciones que se podran hacer es a las variables,
y con stas no se hace porque utilizan una expresin propia, no un valor fijo. Puede escribirse, en
vez de una expresin algo como esto: 5

As estara asignado este valor, y funcionara como una constante. Pero tambin se podra escribir
esto otro:

COPY(BaseDatos.Nombre,1,4)

Entonces s sera una variable, y dependera del campo Nombre en la tabla BaseDatos. Continuar
hablando de las variables, estructuras y posibilidades de todo esto en futuros captulos.

Ahora vamos a hacer un repaso de los ltimos detalles que parecen de inters a la hora de generar
informes con Quick Report.

Unicamente recordar que el signo igual ( = ) no sirve para asignar, ya que las variables tienen su
propia expresin, que puede ser un valor fijo o depender de otras variables y/o campos de una
tabla.

Expresiones
Este lenguaje, a diferencia de la mayora, nicamente busca mostrar unos datos, que suelen salir
de una tabla o varias, y proporcionrselos al usuario. Como tiene ese objetivo, el resultado final del
cdigo que escribamos no se almacenar en ningn lugar, sino que se muestra en el control.
El Rinconcito de Delphi Nstor Freire
8
Por ejemplo: en una tabla tengo un campo booleano, llamado Bool. Si quiero mostrar el contenido
en un informe escribira:

Tabla.Bool

Esto mostrara en el control el texto True. Si quisiera decir Si/No tendra que usar un If:

If (Tabla.Bool, Si, No)

Y si quisiera que apareciera un texto, slo tengo que sumrselo:

Resultado: + If (Tabla.Bool, Si, No)

Para sumar nmeros se hace lo mismo: 5 + 4. Si se quiere sumar un nmero con una variable o
dos variables simplemente se escribe:

4 + NumPag

El texto puede estar en una variable. Aqu hay que utilizar la funcin Str():

Valor: + Str(NumPag)

Variables

Antes de empezar, quiero decir que las variables no existen en las versiones de Q. Report que se
distribuyen con Delphi 3 ni anteriores. En el de Delphi 5 hay dos tipos de variables: las locales, que
slo pueden ser usadas por el control que las cre y las globales, que pueden usarse en todos los
controles que admitan este lenguaje. Las variables no tienen un tipo definido, cualquiera puede
almacenar cualquier valor.
En Delphi 5 hay seis variables por defecto. Estas son:

Locales
- PageNumber : Nmero actual de pgina
- ColumnNumber : Nmero de columnas
- ReportTitle : Nombre del informe (Est almacenado en la propiedad Title de TQuickRep)

Globales
- AppStartTime : Hora de inicio de la aplicacin
- AppStartDate : Fecha de inicio de la aplicacin
- AppName : Nombre de la aplicacin

(La fecha y la hora las trata como tipo String.)

Adems de estas se pueden crear ms. En la creacin se pide el nombre y la expresin. Si la
expresin siempre devuelve el mismo valor (5; 8+6; Hola) entonces se pude considerar como una
constante. En caso contrario, se puede escribir una expresin de una sola lnea, que determinar el
contenido en el momento en que se lea.

Al principio dije que haba tres componentes que podan usar este lenguaje. Para usar el TQRExpr
simplemente se modifica su propiedad Expression. El componente TQRExprMemo es una
combinacin de TQRMemo y TQRExpr. Se escribe el texto literal como si fuera en Tmemo, y
El Rinconcito de Delphi Nstor Freire
9
entre corchetes ( {} ) la expresin correspondiente, sin hacer referencia a la tabla (P.e:
Tabla1.Nombre -> {Nombre} ).

Los TQRGroup es el tercer componente. Estos controles crean los grupos basndose en la
expresin introducida. Cada vez que el resultado de la expresin cambie, se crear un nuevo grupo
(P.e: Si se quiere agrupar los nombres por ndice alfabtico, habra que escribir:
Copy(Tabla1.Nombre,0,1) de esta manera, cuando cambiara la primera letra, los separara de los
anteriores).


Unir Informes
La unin de dos o ms reportajes es bastante fcil. Se necesitan tener todos los informes creados y
un componente del tipo TQRCompositeReport. Este tiene una propiedad llamada Reports, que no
aparece en la ventana del inspector de objetos, por lo que slo est disponible en ejecucin. Esta
propiedad es del tipo TList, por lo que tiene la Items, en la cual se deben aadir punteros a los
informes que se quieran unir. Despus se llama al evento Preview y los informes se mostrarn.

Como los informes pueden tener valores distintos en sus propiedades, el componente
TQRCompositeReport tiene las propiedades de tamao de hoja y opciones, adems del nombre del
informe resultante. Hay que tener cuidado, al disear los informes, de que estas propiedades no
difieran mucho unas de otras, o podra tener problemas al visualizar y/o imprimir el resultado.

Para unirlos debe escribir en su evento OnAddReports el nombre de los reportajes que desee unir,
en el orden en que deban aparecer. Por ejemplo:

Procedure Tform1.TQRCompositeAddReports(Sender:Tobject);
Begin
CompositeReport1.Reports.Add(TquickRep1);
CompositeReport1.Reports.Add(TquickRep2);
End;

Y luego podr llamar a TQRCompositeReport.Preview.

Componente TQRChart
El componente TQRChar sirve, igual que su otra versin TChar, para mostrar grficos en pantalla.
Este componente est preparado para usarse con TQuickReport, por lo que carece de muchas de las
propiedades de su hemano, ya que se supone que los datos no se conocen en la creacin del
informe, y tendr que aadirse los valores a mano. A pesar de esta carencia, tiene las mismas
funciones que el otro, ya que todas estn incluidas en la propiedad Char, de la que las dos versiones
disponen. Para ms informacin en creacin de grficos y uso de estos componentes, ver los
artculos sobre TeeChart de Jos Luis Freire.

Unin de bandas
Hay veces que se necesita intercalar una banda entre otras dos que van juntas, o unir una banda
con otra. Para hacer esto, hay tres opciones: Incluir los datos a intercalar en la banda en que tenga
que ir delante, crear una banda TQRChildBand, o dejar que lo haga Delphi. Para crearla
simplemente se coge de la pestaa QuickReport, se deja en el informe y se modifica la propiedad
ParentBand para indicar a quin debe unirse. Una vez hecho esto, se unir a la zona inferior de la
banda designada. Para que lo cree el ordenador, se elige la banda a la cual deba unirse, y si tiene la
propiedad HasChild, se modifica a True, y ya se crea la banda y se une sola.
El Rinconcito de Delphi Nstor Freire
10

Estas bandas se imprimirn siempre despus de su padre, y cada vez que este aparezca, aparecer
la hija.
Una de estas hijas puede tener otra, y esta otra ms, siempre que ninguna de ellas haga referencia a
alguna banda con la que ya tuviera relacin. As, se pueden tener cinco hijas unidas unas con otras,
pero la primera no se podra unir con la tercera, ya que, indirectamente, se encuentran unidas. Dara
un error y deshara el vnculo.

Potrebbero piacerti anche