Saltar al contenido

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

17 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 Core, MVC, Blazor, 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.

30 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

Unknown 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é María 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é María 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!

Unknown 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

Unknown dijo...

Me refiero a poder justificar el campo en el formulario pdf

José María 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é María 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!

Ana Cris 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é María 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!

Ana Cris dijo...

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

José María Aguilar dijo...

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

sludos

Unknown dijo...

Es posible utilizar esto para una aplicacion de escritorio?

José María Aguilar dijo...

Sí, claro :)

Gustavo dijo...

Buenas.

Capaz que me equivoco, pero ahora la licencia de iTextSharp cambió y ya no se puede incluír así sin más en cualquier aplicación, sino que debe comprarse una licencia para su distribución (en mi contexto específico para una aplicación web).

Lo menciono para quien lee este artículo en estos tiempos ¿correcto?

Gran saludo desde Uruguay,
Gustavo.-

José María Aguilar dijo...

Hola,

Sí, es necesario comprar la licencia si el software en el que vas a usarlo es comercial. Si es open source sí podrías usarlo de forma gratuita.

Muchas gracias por la aportación!

Paul Whiskey dijo...

Hola, que tal.

Podrías realizar una entrada de como mandar a llamar un report rdlc en un proyecto asp.net mvc 4, te lo agradecería bastante.

Gracias, saludos.

José María Aguilar dijo...

Hola!

Uf, hace años que no trabajo con ese tipo de reports, y probablemente en este momento no sería capaz de escribir algo medianamente actualizado :(

De todas formas, veo que hay bastante información al respecto en la red, como la proporcionada por este hilo de SO: https://stackoverflow.com/questions/39042863/mvc-5-how-to-use-an-object-in-rdlc-report.

Saludos!

Unknown dijo...

perfecto tu post, me funciono perfectamente, ahora tengo una duda, como hago algo parecido pero con una imagen? la tengo en un picture box en c# como lo paso al "formulario"? gracias por todo! de antemano

Unknown dijo...

hola quiza mi pregunta no sea adecuada. pero como ejecuto el memtodo en un boton de asp.net?

esque me marca error al solo invocar fillpdf();

alparecer necesita parametros dentro pero nose que poner la verdad.

espero me puedas ayudar gracias!!!

José María Aguilar dijo...

Hola!

El método btnGenerarPDF_Click() que aparece en el post hace precisamente eso, generar el pdf desde la pulsación de un botón de asp.net webforms.

De todas formas, este post es del año 2009, y aunque los conceptos son válidos, todo ha cambiado bastante en cuanto a tecnologías.

Saludos!

Unknown dijo...

Oh! al parecer tuVe una confusión pero ya analice bine e implemente y salio bien en MVC5

GRACIAS JOSE!!! (SOY NUEVO EN LA INDUSTRIA DE DESARROLLO DE SOFTWARE)

Unknown dijo...

hola tengo otra duda y espero me puedas ayudar porque he intentado y aun no resuelvo...

bueno mi duda es la siguiente: Al introducir los valores a los campos de mi plantilla pdf quiero cambiar la fuente de las letras y el tamaño... pero aun no encuentro algo que me solucione y este codigo es el que mas o menos creo que me ayudará.

var Aparajita = BaseFont.CreateFont("C:/Windows/Fonts/Aparajita", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Font font = new Font(Aparajita, 40);
Paragraph PARA = new Paragraph("DIPLOMA", font);

al invocar PARA me marca error, espero me puedan ayudar Gracias!!!

Encarna dijo...

Hola,

lo primero muchas gracias por el post, está genial. Mi duda es acerca del cambio de versión de iTextSharp de la versión 5 a la nueva versión 7, ya que no tiene nada que ver una con la otra y me gustaría saber si tienes algún ejemplo parecido a este pero en la versión 7.

Muchas gracias por adelantado.

Saludos,

Encarna.

José María Aguilar dijo...

Muchas gracias! No, lo siento, el contenido no está actualizado a otras versiones.

Saludos!