Developer's Diary

23 mayo, 2013

Creando PDF en C# (Apache Fop II)

Filed under: .net, ASP.Net, BBDD, Curso C#, Uncategorized, Web — Etiquetas: , , , , , , , — jnavero @ 9:04 PM

En el articulo anterior (Creando PDF en C# (Apache Fop I)) hablábamos de los pasos iniciales para crear nuestro primer pdf “Hola mundo” en C# en realidad es mas bien poco útil pero, bueno debemos ir poco a poco para ir conociendo las estructuras. En el post de hoy vamos a dar un pequeño repaso a la serialización de una clase para poder generarnos un XML. Posteriormente, crearemos una plantilla XSL y uniremos ambos para generar un PDF. Comencemos pues a crearnos nuestra clase de ejemplo para serializarla.

Si desea mas información sobre serialización puede visitar este post: Curso de C# – Control de Ficheros II

Para el ejemplo vamos a hacer una “Agenda” en la que tendremos personas y teléfonos.

Aquí dejo el código que he creado para nuestro ejemplo:

Clase Agenda: Es la clase principal de donde cuelga todo…


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Devthisblog_FOP.Clases
{
[Serializable()]
public class Agenda
{
public List LstPersonas { get; set; }
public Agenda()
{
LstPersonas = new List();
}
}
}

Clase personas:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Devthisblog_FOP.Clases
{
[Serializable()]
public class persona
{
public string Nombre { get; set; }
public string Apellidos { get; set; }
public string Mote { get; set; }
public List LstTelefonos { get; set; }

public persona()
{
LstTelefonos = new List();
}

public persona(string nombre, string apellidos, string mote)
{
this.Nombre = nombre;
this.Apellidos = apellidos;
this.Mote = mote;
LstTelefonos = new List();
}
}
}

Clase Teléfonos:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Devthisblog_FOP.Clases
{
[Serializable()]
public class telefono
{
public string Numero { get; set; }
public string Tipo { get; set; }

public telefono()
{
}

public telefono(string numero, string tipo)
{
this.Numero = numero;
this.Tipo = tipo;
}

}
}

También he creado una clase, para rellenar datos con los que trabajaremos posteriormente. Esta clase es la siguiente

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Devthisblog_FOP.Clases
{
class GenerarDatos
{
//Le meto datos de ejemplo para hacer las pruebas y la serializacion posterior...
public static Agenda IntroduceDatos()
{
Agenda ag = new Agenda();

ag.LstPersonas.Add(new persona("Pedro", "Perez", "Pedrito"));
ag.LstPersonas.Add(new persona("Rodrigo", "Garcia", "Choco"));
ag.LstPersonas.Add(new persona("Juan", "Rodriguez", "Patapalo"));

ag.LstPersonas[0].LstTelefonos.Add(new telefono("666777888", "Movil"));
ag.LstPersonas[0].LstTelefonos.Add(new telefono("111222333", "Casa"));

ag.LstPersonas[1].LstTelefonos.Add(new telefono("666777999", "Movil"));
ag.LstPersonas[1].LstTelefonos.Add(new telefono("333222111", "Casa"));

ag.LstPersonas[2].LstTelefonos.Add(new telefono("666777666", "Movil"));

return ag;
}
}
}

Con estos datos, en el ejemplo mostrado en el post del FOP I, he metido otro botón para que serialice todo lo anterior, el código de dicho botón queda de esta forma:


private void btnAgenda_Click(object sender, EventArgs e)
{
Clases.Agenda ag = Clases.GenerarDatos.IntroduceDatos();
XmlSerializer x = new XmlSerializer(ag.GetType());
System.IO.StringWriter writer = new System.IO.StringWriter();
x.Serialize(writer, ag);
ConvierteFOP(writer);
MessageBox.Show("PDF CREADO...");
}

Con esto ya tenemos la primera parte de para nuestro ejemplo. Ahora vamos a crearnos una plantilla para usar alguno de estos datos, aunque el siguiente post, hablare con mas profundidad de ellas y usaré todos los datos de este ejemplo.

--- Cabecera ---

--- Pie de pagina ---

Falta una cosa en toda esta retaila que he soltado aquí, es la mezcla del XML y del XSL. Expongo el código a continuación y no se si explicar un poco el código o dejarlo para la parte 3 ya que este post se está alargando mucho por toda la cantidad de código que he puesto en este post.


private void ConvierteFOP(System.IO.StringWriter Xmlaux)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(Xmlaux.ToString());
string XSLFO = null;
dynamic xslt = new XslCompiledTransform();
xslt.Load("PlantillaAgenda.xsl");// Aqui va el path de la plantilla
using (System.IO.StringWriter tmp = new System.IO.StringWriter())
{
using (XmlTextWriter res = new XmlTextWriter(tmp))
{
xslt.Transform(xmlDoc, null, res);
XSLFO = tmp.ToString();
}
}
//NOTA: La generacion de PDF en depuracion tarda bastante, en ejecucion es practicamente inmediata
GeneraPDF(XSLFO);
}

Una breve explicación: (Como comenté anteriormente, lo veré mas detenidamente en el siguiente post).

Los primeros archivos puestos (agenda, personas y teléfonos) son las clases con las que trabajaremos, están nuestros datos que pueden llegarnos desde una base de datos o desde cualquier otro sitio, en el caso del ejemplo, se ha creado una función que rellenará la estructura. En el caso del ejemplo tenemos tres personas, pero en nuestro pdf solo aparecerá una, esto lo explicaré en el próximo post.

Posteriormente, en nuestro formulario he creado un botón que llama a la función btnAgenda_Click, esta función monta nuestro XML y lo serializa como indique anteriormente (para mas información sobre la serialización visita el enlace del principio). Dicha función llama a ConvierteFOP al que se le pasa el XML serializado esta función enfrenta el XML con los datos y el XSL que es la plantilla donde le indicaremos la forma en la que se mostrarán los datos si todo está correcto, nos genera un XSL-FO no es mas que un fichero XML ya formateado y con las características para poder ser transformado tal y como vimos en la primera parte de esta serie de post.

El único cambio que debemos hacerle a esa función es que en vez de coger el .FO desde un archivo lo cogemos desde un string pasado por parámetro.

Con este código modificado me despido de este post para no alargarlo más.


private void GeneraPDF(string XSLFO)
{
FopFactory fopFactory = FopFactory.newInstance();
OutputStream salida = new BufferedOutputStream(new FileOutputStream(new File("EjemploAgenda1.pdf")));
try
{
Fop fop = fopFactory.newFop("application/pdf", salida);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // Identificador
Source src = new StreamSource(new java.io.StringReader(XSLFO));
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
}
finally
{
salida.close(); //Cerramos la salida.
}
}

Sin más, me despido hasta la tercera parte donde explicaré las plantillas un poco mas a fondo, el resto, tanto los XML, la serialización y la transformación a XSL-FO es siempre igual.
Aquí dejo un ejemplo.
Dicho ejemplo contiene los códigos del primer post y de este. Por otro lado, no incluye las librerías FOP por el peso, por lo que tendríamos que instalarlas con el NuGet para poder probarlo.

Anuncios

1 comentario »

  1. […] ← Creando PDF en C# (Apache Fop II) […]

    Pingback por Creando PDF en C# (Apache Fop III) — 25 mayo, 2013 @ 5:53 PM


RSS feed for comments on this post. TrackBack URI

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: