Un 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.
Ya 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:
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
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
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
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.
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
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.
Estimado, gracias por el post, es posible enviar el pdf por email sin tener que guardar en el disco el archivo?
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!
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
Me refiero a poder justificar el campo en el formulario pdf
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!
Disculpa como marcas los check desde itextsharp ¿?
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!
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.
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!
Super tu comentario amigo... perfecto ya lo solucioné... una última consulta como puedo modificar el path donde se envía el documento.???
Simplemente modifica las rutas del código anterior... por ejemplo, establece en la variable path la ruta donde lo quieres almacenar.
sludos
Es posible utilizar esto para una aplicacion de escritorio?
Sí, claro :)
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.-
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!
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.
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!
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
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!!!
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!
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)
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!!!
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.
Muchas gracias! No, lo siento, el contenido no está actualizado a otras versiones.
Saludos!
Enviar un nuevo comentario