Ir al contenido


Foto

Uso de reportes FastReport almacenados en Firebird


  • Por favor identifícate para responder
17 respuestas en este tema

#1 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 10 septiembre 2015 - 01:54

Hola a todos:

Estamos realizando una aplicación en Delphi XE8 en la que necesitamos almacenar y utilizar informes FastReport 5 desde una BBDD Firebird.

Los informes los almacenaríamos en Firebird y el usuario sólo definiría el criterio (where) de los correspondientes querys.

Alguien me puede orientar al respecto o mejor si tiene algún ejemplo?

Saludos y gracias.


  • 0

#2 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 10 septiembre 2015 - 02:22

Bienvenido al foro amigo starlet.

 

De momento tu pregunta es bastante confusa y muy general (al menos para mi). 

 

 

 necesitamos almacenar y utilizar informes FastReport 5 desde una BBDD Firebird.

Los informes los almacenaríamos en Firebird y el usuario sólo definiría el criterio (where) de los correspondientes querys.

 

 

 

Eso quiere decir que los informes con extensión .fp3  ya están hechos y que provienen de alguna parte (otra aplicación, una carpeta con dichos archivos, etc) y que solo necesitas guardarlos en una DB Firebird y luego consultarlos.

De ser así se hace necesario conocer la estructura de tu tabla en la que los vas a guardar (imagino que en formato binario BLOB). Imagino esta tabla con algunos campos como: Fecha, Origen, Quien_Guarda, Nombre_Informe, Informe, etc.

 

También es bueno conocer de que manera te conectas a Firebird, con esa información con gusto te ayudamos.

 

Saludos.


  • 0

#3 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 03:14

Ojo con mezclar las cosas. El criterio no tiene NADA que ver con el reporte. El reporte simplemente sabe que recibe un DataSet (que mas da que tan filtrado este) y lo recorre e imprime.

 

El where es simplemente filtrar el dataset del reporte. Por lo general usarias un componente Query. De alguna u otra forma el usuario disparara alguna accion que provocara que se cree un Query, se establezca (o no) un filtro (where) y luego con eso en la mano llamas a tu reporte.

 

El otro punto que tenes que resolver es lo que te comento Wilson: La carga dinamica del reporte. Probablemente queres usar una estructura como la que te comento. Asi que simplemente se guarda el archivo en formato binario, de la misma manera que se guardan las fotos. Esto lo haces usando clases TStream 

 

Para  cargar el reporte dinamicamente, lo unico que tenes que hacer es, cargar en un TStream el contenido del campo que tiene tu reporte y luego pasarselo al metodo LoadFromStream de la clase TfrxReport

 

Despues, tenes que conectar tu dataset con el que usa el reporte; y ahi es cuando ya podes llamar tranquilamente al metodo ShowReport


  • 0

#4 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 10 septiembre 2015 - 03:27

Estimados:

 

Gracias por sus respuestas. Les amplío la información:

 

Los reportes ya están en .fp3 y por la cantidad de los mismos, hemos decidido, su almacenamiento en la base de datos. Estamos utilizando una estructura parecida a la que indica Wilson conectándonos a Firebird con Unidac. 

 

Vemos los siguientes problemas:

 

Como los reportes utilizan cada uno campos concretos y para hacerlo todo dinámico, queremos crear el (los) querys necesarios de manera dinámica, guardando junto al reporte, la consulta que devuelva los campos concretos utilizados en cada reporte (select .... from tabla ), que se creen los fields del query de manera dinámica, dando la posibilidad al usuario de definir el where para cada situación y estamos un poco perdidos en todo el proceso.

 

Saludos,

 

 


  • 0

#5 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 11 septiembre 2015 - 10:16

Vamos por partes, entonces  de momento están perdidos en saber como obtener la consulta (y los campos) de la consulta que origina el informe?

 

De ser así sería bueno saber de que manera obtienen el .fp3 para poder continuar.

 

Si en cambio,  junto al informe ya cuentan con la consulta, entonces comenten para analizar los pasos a seguir.

 

Saludos.


  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 11 septiembre 2015 - 10:37

Hola starlet bienvenid@ a DelphiAccess.

 

Aún no entiendo cuando dices que quieres almacenar el reporte en la base de datos.

 

Desde donde lo veo, lo único que tienes que hacer como bien dice Agustín, es solo "pasar" un dataset, que previamente has creado en tiempo de ejecución.

 

Lo de guardar los reportes, no veo problema, si ya tienes los archivos .fp3 solo necesitas asignar el dataset que creaste al dataset que tengas en el reporte.

 

Y como dice Wilson, si nos das mas información podremos ayudarte mejor.

 

Saludos


  • 0

#7 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 11 septiembre 2015 - 12:21

Estimados:

 

Intentaré explicarles donde está nuestro problema.

 

Actualmente, tenemos una aplicación con unos 50 reportes, que distribuimos junto con la aplicación. Estos reportes utilizan unos datasets (querys) que tenemos creados en un datamodule (unos 50 querys, uno para cada reporte).

 

Todo esto nos funciona correctamente.

 

Lo que intentamos hacer es lo siguiente :

 

- Guardar los .fr3 en una base de datos en un campo blob.para no tener que distribuir los 50 reportes (o más si surgen nuevos ) En eso no hay problema.

 

Es nn los siguientes pasos es donde tenemos dudas:

 

Cuando el usuario seleccione un reporte, creamos en tiempo de ejecución ese reporte, o tenemos un reporte base ya en la aplicación y lo utilizamos para hacer un loadfromstream?. Que ventajas hay en cada caso?

 

Para no tener que recompilar la aplicación para crear un query nuevo cada vez que se añada un nuevo reporte a la base de datos, en un campo de la bbdd, tenemos el "select  ... from ... "  correspondiente, que devuelve los campos necesarios para dicho reporte. Queremos crear en tiempo de ejecución ese query y que los campos también se creen y vincular ese dataset al reporte correspondiente. Eso no tenemos muy claro como poder hacerlo.

 

Espero poder haberme explicado mejor.

 

Gracias por su ayuda.

 

Saludos


  • 0

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 11 septiembre 2015 - 12:58

Hola

 

Hay otra opción, aunque no se si la tiene tu componente, la versión con la que hice la prueba es la 5.

 

La idea es que puedes incrustar los reportes en el DFM de la aplicación. La desventaja es que el tamaño del ejecutable aumentará dependiendo de la complejidad de los reportes, aunque...., se podría separar utilizando BPL's o DLL's, etc.

 

Adjunto imágenes de como funciona este asunto.

 

Saludos

 

Archivos adjuntos


  • 0

#9 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 11 septiembre 2015 - 01:53

Si Egostar, la contemplamos y la descartamos por:

 

- tamaño, aunque como bien dices se podrían utilizar packages o DLL

- Y principalmente, porque habría que recompilar la aplicación y redistribuirla cada vez que se añada/cambie algún reporte.

 

Esa forma de trabajar que planteo, la he visto en alguna aplicación y siempre me ha parecido una muy buena forma de trabajar, independizando los reportes del código.

 

La idea que tenemos (no se si lo conseguiremos...aunque seguro que con la ayuda de algún maestro del foro ) es hacerlo independiente de la aplicación y dinámico.

 

gracias,

 

Saludos,


  • 0

#10 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 11 septiembre 2015 - 02:55

Basicamente un FastReport, por lo menos como lo hago yo que aun no lo he exprimido del todo, seria algo asi:

 

Un form con:

TFrxReport, TFrxDBDataSet (1 seguro, 2 si es maestro/detalle), TDataSource (enlaza maestro/detalle)

Varios componentes para exportar (PDFExport, etc)

 

Eso esta metido en el exe

 

Luego, hay dos constructores posibles:


delphi
  1. constructor Create(AOwner: TComponent; ADataSet: TDataSet; AFilename: string); overload;
  2. constructor Create(AOwner: TComponent; AMaster, ADetail: TDataSet; AFilename: string); overload;
  3. constructor Create(AOwner: TComponent; ADataSet: TDataSet; AReportFile: TStream); overload;
  4. constructor Create(AOwner: TComponent; AMaster, ADetail: TDataSet; AReportFile: TStream); overload;

Con eso podrias inicializar casi cualquier reporte.

 

Ahora, el problema es el frxDBDataSet. Hay que cargar los Alias que usa el FastReport. Hay 2 alternativas que se me ocurren rapido. 

 

(La verdad no estoy seguro si se incluye dentro del archivo .fr3)

 

1) Recorrer el dataset e ir creando los alias, corriendo el riesgo que quien diseño el reporte, al campo "nombre" lo refiere en su reporte como "NombrePersona"

 

2) Guardar la lista de alias en la tabla, y agregarla al constructor obviamente


  • 0

#11 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 11 septiembre 2015 - 03:06

Aclárenme algo, en realidad lo que están guardando en la DB son los diseños de los reportes de extensión .fr3 y no informes (reportes con datos) de extensión .fp3, como parecía en principio.

 

De ser así, surgen nuevas preguntas:

 

-Quien crea los nuevos reportes, los desarrolladores o los usuarios (FR permite que el usuario cree o modifique un reporte).

 

-Si los creadores de los nuevos reportes son los desarrolladores, en el modelo que plantean, no tienen que recompilar la aplicación, pero si tendrían que enviar la actualización (nuevos reportes) a las bases de datos. Para esto no necesitan ayuda porque es lo que vienen haciendo.

 

-Si quienes crean o modifican los reportes son los usuarios hay muchas formas de encarar el problema.

 

1- Ustedes (desarrolladores) podrían asignar los datasets en cuestión  a un reporte en blanco (solo con las bandas) que sirva de plantilla y guardarlo en la db, como vienen haciendo. Luego en FR es fácil que el usuario escoja los campos que prefiera y que los coloque en el lugar que quiera (eso ya viene listo). Bastaría guardar el nuevo reporte modificado, con otro nombre en la db.

 

2- A partir de un dataset o de un dbGrid o similar (para obtener los campos y sus tipos) se podría crear en RunTime un reporte, hay muchos ejemplos en la documentación y en los foros de FR, aquí te pongo algunos..

 

https://www.fast-rep...nual_report.htm

 

https://www.fast-rep...m_from_code.htm

 

https://www.fast-rep...?showtopic=4976

 

En cuanto más claridad haya en tu pregunta habrán mas posibilidades de ayudar.

 

Saludos. 


  • 0

#12 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 11 septiembre 2015 - 03:38

Muchas gracias por las respuestas.

 

El planteamiento es como dice Wilson. Almacenamos .fr3 y el query en la bbdd. Nosotros nos encargamos de añadir/modificar los reportes..

 

En cuanto a los querys, nosotros en el mismo query especificamos los alias si fuera el caso (select campo_nombre nombre, código_identificacion codigo from tabla).

 

La idea es crearlo todo en runtime sacando los valores de la bbdd y q el usuario solo especifique el criterio (where...order by...)

 

Voy a echar un vistazo a los links sugeridos a ver si me aportan algo de luz...

 

Gracias y saludos


  • 0

#13 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 11 septiembre 2015 - 04:50

Por fin entiendo, en realidad no tiene nada que ver  con el reporte (este sigue siendo el mismo ya que los campos son los mismos), sino con  la sentencia SQL que se le pasa al dataset, ahora bien para ese cometido, si quieren ahorrar tiempo y trabajo hay componentes de terceros listos para eso, por ejemplo: (http://www.sqlmanage...s/querybuilder/), y si quieren hacerlo a mano, postea un ejemplo de una consulta sencilla (la que llevaría el dataset) y  el texto de lo que guardarían para esa consulta en la tabla de reportes.  Con eso miramos posibles soluciones.

 

Saludos.


  • 0

#14 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 11 septiembre 2015 - 05:10

Una forma de encarar el problema sería, crear una tabla de detalles con tres campos (id_reporte, nombre_campo, tipo_campo), aquí se guardarían los campos de cada reporte  (dataset) susceptibles de parametrizar , en donde id_reporte apunta al id del reporte de la tabla maestra. En la tabla maestra los campos (id_reporte, consulta, nombre_dataset, reporte ), en el campo consulta colocar la sentencia sin el WHERE.

 

Luego cuando el usuario escoge el reporte se hace una consulta a la tabla maestra y a la de detalles,  de ese modo se obtiene  la primera parte de la sentencia y  los campos de esta (que están en la tabla de detalles) con esa información, en un form modal agregamos dinámicamente por cada campo un label con el nombre del campo, y un componente idóneo para el tipo de datos del campo para que el usuario especifique el valor del parámetro y, además  un chekBox para decida si tiene en cuenta ese criterio. En ese punto con la información recavada en el form construyo la segunda  parte de la sentencia, la uno con la que extraje de la tabla maestra y se la paso al dataset.

 

No es tan complicado.

 

Saludos.


  • 0

#15 FerCastro

FerCastro

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 636 mensajes
  • LocationCiudad de México

Escrito 12 septiembre 2015 - 02:55

A ver llegué tarde a la pregunta y no se si ya la terminaron de responder (me ha dado flojera ller todo).

 

Pero te comento que yo hice algo que quieres hacer y solo es guardar en dos campos (yo uso blob) uno el FR3 y en otro la sentencia que va al dataset del reporte.

 

Si gustas y esto es lo que buscas dime para ampliarlo.

 

Saludos!


  • 0

#16 starlet

starlet

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 13 septiembre 2015 - 02:48

Gracias FerCastro:

 

Si, me interesa que aportes tu experiencía ya que lo has implementado y si encontraste alguna desventaja al realizarlo de esta manera.

 

Saludos,


  • 0

#17 FerCastro

FerCastro

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 636 mensajes
  • LocationCiudad de México

Escrito 13 septiembre 2015 - 04:00

Hola Starlet

 

Mira te comento que una vez un cliente me solicitó un reporteador visual, y lo que se me ocurrió fue utilizar el fast report, que permite instanciar el diseñador visual en tiempo de ejecución.

 

La verdad es que al hacer esto le das la herramienta al cliente de generar sus propios reportes, aunque para esto requiere conocer un poco de SQL (yo lo hice con MySQL). Y lo bueno de esto es que el reporte queda guardado y si lo quieres parametrizar, cambiar, etc, pues lo haces y lo reutilizas según lo necesites.

 

Te dejo unas imágenes para que pueda ver algo

 

- No, la página me dice que falló la subida de las imágenes.

.

 

 


  • 0

#18 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 15 septiembre 2015 - 06:00

Hola, creo que llegué tarde también, pero espero que mi comentario ayude también.

 

Los reportes de fastreport tienen dos componentes, un DataSet y el reporte en si,  es fácil guardar el reporte y leerlo desde una base de datos, en Delphi se realiza de la siguiente manera.


delphi
  1. //Guardarlo en una tabla
  2. Var
  3. St : TMemoryStream;
  4. Begin
  5. St := TMemoryStream.Create;
  6. FRReport1.SaveToStream(St);
  7. St.Position := 0;
  8. TBlobField(Query.FieldByName('CampoBlob')).LoadFromStream(St);

Debes tener en cuenta de leer el sql de la base de datos también e inicializar el dataset asociado al reporte.

 

Para leerlo es algo similar


delphi
  1. Var
  2. St : TMemoryStream;
  3. Begin
  4. St := TMemoryStream.Create;
  5. TBlobField(Query.FieldByName('CampoBlob')).SaveToStream(St);
  6. St.Position := 0;
  7. FRReport1.LoadFromStream(St);

Debes inicializar el query y llamar la función FRReport1.prepare;

 

Espero sea de utilidad

 

Saludos.


  • 0




IP.Board spam blocked by CleanTalk.