Autor en Google+
Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET, ASP.NET Core, MVC, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

10 años online 🎂

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET, ASP.NET Core, MVC, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 14 de julio de 2009

Formulario PDFUn post en .NET Answers me ha recordado que hace tiempo tenía pendiente escribir una entrada para comentar la técnica que he utilizado en más de una ocasión para generar documentos PDF desde mis aplicaciones .NET de forma muy sencilla, y que puede aplicarse en escenarios donde se conozca de antemano el diseño del documento a imprimir y sólo sea necesario introducir información concreta en espacios muy definidos. Un caso muy habitual es el rellenado de formularios o impresos, aunque usando un poco la imaginación seguro que podéis encontrarle muchas más utilidades.

La técnica consiste en crear, utilizando alguna herramienta de diseño como Adobe Acrobat, un documento PDF que contenga todos los contenidos estáticos del documento que deseamos generar. En cada zona donde queremos inyectar contenido deberemos introducir un campo de formulario (por ejemplo, “nombre”, “apellidos”, etc.) adaptando el tipo de letra, límites y las propiedades del campo que sean necesarias.

imageYa desde código el procedimiento será bien sencillo: abrimos la plantilla, introducimos los valores en cada uno de los campos, y hacemos con el documento resultante lo que nos convenga según la ocasión: enviarlo por email, salvarlo a disco, ofrecerlo para la descarga, etc.

Para conseguir estos objetivos utilizaremos iTextSharp, una adaptación para .NET de la librería iText, muy conocida en el mundo Java. Por tanto, en primer lugar, es necesario descargarla desde Sourceforge, y referenciarla en el proyecto desde el cual vamos a utilizarla.

El siguiente código implementa un método realiza el procedimiento descrito:

   1: public void FillPDF(string templateFile, Stream stream)
   2: {
   3:     // Abrimos la plantilla y creamos una copia, sobre
   4:     // la cual trabajaremos...
   5:     PdfReader reader = new PdfReader(templateFile);
   6:     PdfStamper stamp = new PdfStamper(reader, stream);
   7:  
   8:     // Introducimos el valor en los campos del formulario...
   9:     stamp.AcroFields.SetField("Nombre", "Juan");
  10:     stamp.AcroFields.SetField("Apellidos", "Rodríguez Méndez");
  11:  
  12:     // Fijamos los valores y enviamos el resultado al stream...
  13:     stamp.FormFlattening = true;
  14:     stamp.Close(); 
  15: }

Así, para almacenar la plantilla con los datos en un nuevo PDF, bastaría con invocar al método anterior de la siguiente manera:


   1: Stream file = new FileStream("FormularioRelleno.pdf", FileMode.Create);
   2: FillPDF("plantilla.pdf", file);

O si queremos que desde una aplicación ASP.NET el usuario pudiera descargarlo directamente, podríamos utilizar un código como el siguiente:



   1: protected void btnGenerarPDF_Click(object sender, EventArgs e)
   2: {
   3:     Response.Clear();
   4:     Response.ContentType = "application/pdf";
   5:     Response.AddHeader("content-disposition", "attachment;filename=Formulario.pdf");
   6:     FillPDF(Server.MapPath("Plantilla.pdf"), Response.OutputStream);
   7: }

Por último, sólo comentar que iTextSharp no sólo es útil para rellenar formularios, ni mucho menos. Se trata de una librería muy potente que permite la creación y edición al vuelo de documentos PDF completos, y dispone de un complejo amplísimo API que nos permite hacer casi de todo con ellos. Además, se distribuye bajo licencias LGPL y MPL, muy permisivas ambas, por lo que pueden ser utilizadas en prácticamente cualquier tipo de sistemas.

Para el que no se le apetezca teclear mucho, ahí va una solución para Visual Studio 2005 con dos proyectos, uno web y otro de consola, demostrando el funcionamiento.






Publicado en: Variable not found.

Estos contenidos se publican bajo una licencia de Creative Commons Licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 3.0 España de Creative Commons

17 Comentarios:

Anónimo dijo...

Hola José quería darte las gracias por este post, busque mucho por internet, y esto fue lo único que me sirvió, ahora estoy tratando de personalizar un PDF, pero he tenido problemas y no sé como solucionar esto, tu nombraste que el PDF tiene que ser estático, pero al momento en que lo guardo ahí le defino esa opción, bueno de todas maneras voy a seguir intentando de descubrir mi problema con el PDF.
Saludos

Miguel

Moisés Rivas dijo...

Hola Jose te cuento que estoy realizando un administrador de template de pdf, el cual extraigo de una db los template y relleno algunos campos, despues muestro este pdf en un embed y de ahi lo dejo editable para que alguien pueda cambiar los datos, lo que quiero hacer es capturar los eventos que se realizan para ir guardando los datos que se modifican o en su defecto agregar un boton que diga guardar y asi guardo el pdf que se lleno.

Desde ya agradesco tu tiempo y muy bueno el post, espero tu respuesta. Saludos

Jose Cruz dijo...

Hola Jose queria saber si tienes algun ejemplo con un campo image en PDF ya que yo cree un formulario con Adobe Designer ES e inserte un campo imagen pero el problemas es que no me inseta nada. y gracias por el ejemplo

José M. Aguilar dijo...

Hola!

Cuando he necesitado incluir imágenes nunca lo he hecho con formularios, sino mediante los mecanismos ofrecidos por itextsharp para "dibujar" este tipo de recursos sobre las páginas.

A ver si te vale algo así: http://www.mikesdotnetting.com/Article/87/iTextSharp-Working-with-images

Saludos.

Estefania dijo...

Hola!
Yo tengo una plantilla que cumplimento con datos y retorno en PDF plano.
Ahora necesito que conserve algunos Acrofields de tipo checkbox para poderlos editar a posteriori.
¿Cómo puedo conseguir que el pdf que genero sea editable?

Gracias

José M. Aguilar dijo...

Hola!

En estos momentos estoy de viaje y no puedo hacer pruebas ni buscar más en profundidad, pero creo recordar que establecer FormFlattening a true es lo que hace que el PDF no sea editable. Prueba simplemente a eliminar esta línea, a ver si te vale.

Saludos.

Almarza dijo...

Estimado, gracias por el post, es posible enviar el pdf por email sin tener que guardar en el disco el archivo?

José M. Aguilar dijo...

Hola,

Sí se podría aunque habría que trabajarlo un poco. Observa que en el método FillPDF del ejemplo se recibe como parámetro el stream de salida, nada impide que este stream pueda ser de in buffer en memoria (es decir, un memory stream). Si lo creas sobre un stream en memoria, ya sólo tendrás que buscar la forma de atachaelo al email que vayas a enviar.

Saludos!

Kike gl dijo...

Hola
que tal el post esta muy bien, pero como le hago para JUSTIFICAR un campo de texto de muchas lineas, se que se puede alinear a la izquierda, derecha y centrar pero no se como se JUSTIFICA el texto

Kike gl dijo...

Me refiero a poder justificar el campo en el formulario pdf

José M. Aguilar dijo...

Hola!

Pues no sabría decirte, no lo he hecho nunca... si no puedes hacerlo desde las propiedades del campo, supongo que tiene mala solución. Quizás podrías usar los métodos de itextsharp para pintar el párrafo alineado sobre el campo, pero no sería sencillo y sólo te valdría en algunos escenarios.

Siento no poder darte más pistas :-(

Saludos!

Soul dijo...

Disculpa como marcas los check desde itextsharp ¿?

José M. Aguilar dijo...

Hola,

es muy parecido al resto de campos, lo que ocurre es que debes establecer el checkbox con el valor que le hayas configurado para su estado "activo".

Puedes leer más aquí:

http://stackoverflow.com/questions/19698771/checking-off-pdf-checkbox-with-itextsharp

Saludos!

Unknown dijo...

Hola amigo excelente el foro y la manera de utilizar este código, sin embargo, tengo un problema, se genera el documento, lo abro, lo mando a guardar en un path definido y listo; pero al momento de volverlo a abrir desde la aplicación o desde la carpeta me sale una de las siguientes opciones 1) "Error al abrir el documento. Este archivo ya está abierto o está siendo utilizado por otra aplicación" o 2)"Adobe Acrobat Reader no puede abrir 'nombre documento.pdf' debido a que no es un tipo de archivo admitido o esta dañado (por ejemplo, se envió como adjunto de correo electrónico y no se descodificó correctamente)."

El código que uso es:
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + NOMBRE_ARCHIVO);
FillPDF(Server.MapPath("Plantilla.pdf"), Response.OutputStream);

//Crear
Stream file = new FileStream(path_destino, FileMode.Create);
Response.Flush();
Response.Close();

Si puedes darme una mano quedaré eternamente agradecida, llevo una semana sin hallar solución.

José M. Aguilar dijo...

Hola!

No sé si he entendido bien lo que pretendes hacer, pero si lo que quieres es guardar en el servidor el archivo y al mismo tiempo retornarlo al usuario, podrías hacerlo así:

// Primero lo guardamos en el servidor...
var path = Server.MapPath("Output.pdf");
using (Stream file = new FileStream(path, FileMode.Create))
{
FillPDF(Server.MapPath("Plantilla.pdf"), file);
}

// Y después lo enviamos al navegador del usuario...

Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=Formulario.pdf");
Response.WriteFile(path);


Espero que te sea de ayuda.

Saludos!

Unknown dijo...

Super tu comentario amigo... perfecto ya lo solucioné... una última consulta como puedo modificar el path donde se envía el documento.???

José M. Aguilar dijo...

Simplemente modifica las rutas del código anterior... por ejemplo, establece en la variable path la ruta donde lo quieres almacenar.

sludos