Está en la página 1de 4

057-060_PDFRepL13 02.12.

2005 11:12 Uhr Página 57

PDF Report • DESARROLLO

Generación de informes profesionales desde Python

REPORTLAB

Hoy en día se hace imprescindible disponer de herramientas que permitan generar informes en PDF de alta

calidad rápida y dinámicamente. Existen diferentes herramientas para esta finalidad, entre ellas cabe

destacar ReportLab, biblioteca gratuita que permite crear documentos PDF empleando como lenguaje de

programación Python. POR ANA M. FERREIRO Y JOSE A. GARCÍA

L
a biblioteca ReportLab crea direc- hay que seguir para instalar y configurar mar ejemplo1.py, las siguientes líneas de
tamente documentos PDF basán- ReportLab. código:
dose en comandos gráficos y sin El paquete pdfgen es el nivel más bajo
pasos intermedios, generando informes para generar documentos PDF, que se from reportlab.pdfgenU
en un tiempo extremada- basa esencialmente en import canvas
mente rápido y siendo de una secuencia de instruc- c=canvas.Canvas("primer.pdf")
gran utilidad en los ciones para “dibujar” c.drawString(50,500, " MiU
siguientes contextos: cada página del docu- PRIMER PDF")
generación dinámica de mento. El objeto que pro- c.drawString(250,300,U
PDFs en aplicaciones web porciona las operaciones "Coordenada=(250,300) ")
(empleado con Zope), de dibujo es el Canvas. El c.drawString(350,200,U
generación de informes y Canvas mide igual que "(350, 10)")
publicación de datos una hoja de papel blan- c.drawString(150,400,U
almacenados en bases de co, con puntos sobre la "Aprendiendo REPORTLAB")
datos, embebiendo el misma identificados c.showPage()
motor de impresión en mediante coordenadas c.save()
aplicaciones para conse- cartesianas (X,Y), que
guir la generación de Figura 1: Coordenadas carte- por defecto tienen el ori- Probamos el programa y vemos que en el
informes a medida, etc. sianas de una hoja. gen (0,0) en la esquina mismo directorio ya se ha creado un fiche-
inferior izquierda de la ro llamado primer.pdf, análogo al que se
Primeros pasos página. La coordenada X va hacia la muestra en la Figura 2, sin necesidad de
Lo primero es tener instalados Python y derecha y la coordenada Y avanza hacia realizar ningún otro paso intermedio.
ReportLab para realizar todas las prue- arriba (ver Figura 1). Mediante la línea from reportlab.pdfgen
bas que van surgiendo y las que se nos Para crear nuestro primer PDF basta import canvas importamos Canvas, utili-
ocurran. En [1] se detallan los pasos que escribir en un fichero, que podemos lla- zado para dibujar en el PDF. El comando

WWW.LINUX- MAGAZINE.ES Número 13 57


057-060_PDFRepL13 02.12.2005 11:12 Uhr Página 58

DESARROLLO • PDF Report

canvas.Canvas(path__fichero) permite El tamaño de las hojas se


indicar el nombre con el que se guardará importa mediante from
el PDF. El método drawString(x,y,cade- reportlab.lib.pagesizes
na_texto) empieza a escribir el texto en la import letter,A4,A5,A, y se
coordenada (x,y) (se puede probar a cam- especifica en el Canvas
biar las diferentes coordenadas). El méto- con la propiedad pagesize.
do showPage() crea la página actual del Muchas veces querremos
documento. Finalmente, save() guarda el adaptar el dibujo a las
fichero en el path indicado. dimensiones de la hoja,
En el ejemplo previo hemos creado un por lo que necesitamos
PDF sin especificar el tamaño del docu- conocer el ancho y el alto
mento, si queremos fijar el tamaño de la de la misma:
hoja (A4, letter, A5, etc.) bastaría indi- ancho=tipo_hoja[0] y
carlo en el Canvas mediante: alto=tipo_hoja[1]; donde
tipo_hoja puede ser letter, Figura 2: Primer documento generado. El resultado impreso
from reportlab.lib.U A4, A5 , etc. refleja cómo controlar las coordenadas de una hoja.
pagesizes import letter,A4,A5,U La clase Canvas dispo-
A3 ne de diferentes herramientas para dibu- tipo de fuente se realiza usando
c=canvas.Canvas("primer.pdf",U jar líneas, circunferencias, rectángulos, canvas.SetFont(tipo_fuente,tamaño). En
pagesize=letter) arcos, etc. Además permite modificar el la Figura 3 se muestra el PDF que crea-
color de los objetos, rotar, trasladar, indi- mos con el simple código del Listado 1.
car tipo y tamaño de fuente, etc. En el Podemos probar a cambiar propiedades
Listado 1: ejemplo2.py código del Listado 1 podemos ver cómo (en el manual de ReportLab encontrare-
01 from reportlab.pdfgen import se dibujan, por ejemplo líneas, mos muchas otras).
canvas mediante canvas.line(x1,y1,x2,y2); cír-
02 culos, empleando el método canvas.cir- Añadiendo imágenes
c=canvas.Canvas("canvas_draw.p cle(x_centro,y_centro,radio,stroke=1,fill En este instante ya podemos demostrar
df") =1); y rectángulos con esquinas redon- nuestra creatividad en dibujo “artístico”,
03 c.setFont("Helvetica",24) deadas, aunque de un modo bastante laborioso.
04 c.line(50,50,50,350) canvas.roundRect(x,y,ancho,alto,angu- Seguro que más de uno preferimos
05 c.line(50,50,350,50) lo,stroke=1,fill=0). Nótese que cada incluir en nuestros ficheros imágenes ya
06 c.setStrokeColorRGB(1,1,0.0) vez que se quiera emplear un color creadas. Pues esto es posible: en el área
07 c.setFillColorRGB(0,0.0,0.5) nuevo hay que indicarlo mediante de descarga de Linux Magazine tenemos
08 canvas.setFillColorRGB(r,g,b), para el la imagen Tux2.png para las diferentes
c.roundRect(75,75,275,275,20,s color de relleno, o pruebas.
troke=0, canvas.setStrokeColorRGB(r,g,b), para A la hora de incluir imágenes podemos
fill=1) fijar el color de las líneas. La elección del optar por las siguientes opciones. La pri-
09 c.setFillColorRGB(0.8,0.,0.2)
10 c.circle(205,205,100,stro-
ke=1,fill=1)
11
c.setFillColorRGB(0.75,0.75,0.
)
12
c.drawString(125,80,"Cuadrado"
)
13 c.setFillColorRGB(0,1,0.2)
14
c.drawString(155,200,"Circulo"
)
15 c.setStrokeColorRGB(1,0,0.0)
16
c.ellipse(75,450,350,335,fill=
0)
17 c.setFillColorRGB(0,0,0.5)
18 c.drawString(150,375,"Elipse")
19 c.showPage()
20 c.save()
Figura 3: Objetos que se pueden dibujar con un Canvas.

58 Número 13 WWW.LINUX- MAGAZINE.ES


057-060_PDFRepL13 02.12.2005 11:12 Uhr Página 59

PDF Report • DESARROLLO

Figura 4: Colocando imágenes con Figura 6: Ejemplo de rotación, traslación y


drawImage. Figura 5: Modo en que se rota, traslada y escalado de imágenes.
escala un objeto Drawing.
mera y más sencilla, pero con la que no los espacios en blanco innecesarios;
nos es posible rotar, trasladar, ni redi- c.drawImage("Tux2,png",200,300,U bulletText indica si el párrafo se escribe
mensionar es mediante el método width=30,height=60) con un punto al inicio del mismo; la
drawImage(image,x,y,width=None,heig fuente y otras propiedades del párrafo y
ht=None) de la clase Canvas (si no se Si lo que pretendemos es rotar imágenes el punto se indican mediante el argu-
especifica el alto y el ancho, coloca la o escalarlas, debemos emplear los obje- mento style. Veamos cómo añadir un
figura con sus dimensiones originales). tos Image(x,y,ancho,alto,path_imagen) y párrafo:
Mediante las siguientes líneas podemos Drawing(ancho,alto) que se importan
crear un fichero similar al de la Figura 4. mediante from reportlab.graphics.shapes 01 fr om repor tlab.lib.styles
import Image, Drawing. El objeto import getSampleStyleSheet
c.drawImage("Tux2.png",0,0) Drawing puede escalarse, rotarse y tras- 02
ladarse; pero hay que tener en cuenta styleSheet=getSampleStyleShee
que todas estas operaciones son acumu- t()
Listado 2: Jugando con lativas (ver Figura 5). En el Listado 2 03 story=[]
imagenes (ejemplo3_2.py) podemos ver cómo emplear correcta- 04 h1=styleSheet['Heading1']
mente estos objetos (Figura 6). 05 h1.pageBreakBefore=0
01 from reportlab.graphics.shapes
Obsérvese que ahora el PDF no se genera 06 h1.keepWithNext=1
import Image, Drawing
a partir de un Canvas, sino que se genera 07 h1.backColor=colors.red
02 from reportlab.graphics import
mediante renderPDF.drawToFile(d,"can- 08 P1=Paragraph("Estilo Cabecera
renderPDF
vas_image2.pdf"), donde - h1 ",h1)
03 from reportlab.lib.pagesizes
d=Drawing(A4[0],A4[1]). Podemos pro- 09 story.append(P)
import A4
bar a modificar los valores de los distin- 10 style=styleSheet['BodyText']
04 inpath="Tux2.png"
tos métodos scale, rotate, translate; 11 P2=Paragraph("Estilo
05 IMAGES=[]
observaremos que a veces la imagen BodyText"
06 d=Drawing(80,100)
puede desaparecer del folio, eso es debi- ,style)
07 img=Image(200,0,80,100,inpath)
do a que los valores que se dan hacen 12 story.append(P2)
08 d.add(img)
que nos salgamos de las dimensiones de
09 d.rotate(45)
la página. El paquete reportlab.lib.styles contiene
10 d.scale(1.5,1.5)
estilos predefinidos. Con
11 IMAGES.append(d)
Creación de párrafos y getSampleStyleSheet obtenemos un estilo
12 d=Drawing(80,100)
tablas ejemplo. Tenemos un estilo para la cabe-
13 d.add(img)
La clase reportlab.platypus.Paragraph cera y otro para el texto normal.
14 d.translate(10,0)
permite escribir texto formateado (justi- Mediante h1.pageBreakBefore=0 deci-
15 d.scale(2,2)
ficado, alineado a la derecha o mos que no queremos un salto de página
16 d.rotate(-5)
izquierda, centrado) en un aspecto ele- cada vez que se escriba una cabecera h1,
17 IMAGES.append(d)
gante, además de modificar el estilo y en caso contrario basta escribir 1. Los
18 d=Drawing(A4[0],A4[1])
color de t r o z o s d e l a l í n e a a t ra - diferentes párrafos se van almacenando
19 for img in IMAGES:
vés de XML. Mediante en la lista story porque posterior-
20 d.add(img)
Paragraph(texto,style,bulletText=None) mente se añaden al pdf a través el
21 renderPDF.drawToFile(d,"can-
se instancia la clase; texto contiene el paquete SimpleDocTemplate de repor-
vas_image2.pdf")
texto del párrafo, en el que se eliminan tlab.platypus:

WWW.LINUX- MAGAZINE.ES Número 13 59


057-060_PDFRepL13 02.12.2005 11:12 Uhr Página 60

DESARROLLO • PDF Report

tener un texto ['Febrero',3000,100.5],U


muy largo. Si ['Marzo',2000,1000],U
añadimos un ['Abril',1500,1500]]
párrafo cuyo
texto sea En una tabla se puede fijar el estilo de
"Hola"*300, cada miembro de la misma. Si por ejem-
seguro que se plo, se quiere que el texto de la primera
generan más de columna sea azul, y que los números
una hoja. sean todos verdes, haremos
Si lo que que-
remos es añadir t.setStyle([U
una tabla, es ('TEXTCOLOR',(0,1),(0,-1),U
necesario impor- colors.blue), ('TEXTCOLOR',U
tar from repor- (1,1), (2,-1),colors.green)])
tlab.platypus
import En el código del Listado 3 mostramos un
Table,TablsStyle. ejemplo en él se ilustra cómo adaptar el
Figura 7: Ejemplo de párrafo, tabla e imagen. Una tabla se crea estilo según se quiera (Figura 7).
añadiendo una Podemos ver que para incluir un nuevo
lista de listas, elemento en el PDF es suficiente con ir
doc=SimpleDocTemplate(U donde cada componente de la lista guar- añadiendo cada objeto a la lista story.
"paragrahp.pdf", pagesize=A4,U da la información de cada fila. Si quere- Ahora ya sabemos todo lo necesario
showBoundary=1) mos construir una tabla de 5 filas y 3 para crear nuestros propios carteles, infor-
doc.build(story) columnas hacemos mes, catálogos, presentaciones, etc. ■

En este caso, se genera un PDF con tan- t=Table([['','Ventas',U RECURSOS


tas páginas como sea necesario. 'Compras'],U
Comprobar esto es tan sencillo como ['Enero',1000, 2000],U [1] Reportlab: http://www.reportlab.org

Listado 3: Crear Tablas y Párrafos (ejemplo4.py)


01 from reportlab.lib.pagesizes 16 P=Paragraph("Estilo Cabecera - 36 story.append(t)
import A4 h1 ",h1) 37
02 from reportlab.lib.styles 17 story.append(P) 38 story.append(Spacer(0,15))
import 18 P=Paragraph("Estilo h2 ",h2) 39 P=Paragraph("Cabecera h1",h1)
19 story.append(P) 40 story.append(P)
getSampleStyleSheet,ParagraphS 20 style=styleSheet['BodyText'] 41
tyle 21 texto=" Texto escrito para ver 42 cadena=''' Mediante ReportLab
03 from reportlab.platypus import como es posible
Spacer, crear ficheros PDF."+\ 43 generar ficheros PDF de
SimpleDocTemplate, Table, 22 "Este parrafo esta escrito gran
TableStyle en estilo BodyText" 44 calidad. Es posible
04 from reportlab.platypus import 23 texto_largo=texto 45 incluir graficos, image-
Paragraph, Image 24 #texto_largo=texto*100 nes,
05 from reportlab.lib import 25 P=Paragraph(texto_largo,style) 46 tablas; creando informes
colors 26 story.append(P) 47 de gran calidad '''
06 27 story.append(Spacer(0,12)) 48 P=Paragraph(cadena,style)
07 28 49
styleSheet=getSampleStyleSheet 29 50 story.append(Spacer(0,15))
() t=Table([['','Ventas','Compras 51
08 story=[] '], 52
09 h1=styleSheet['Heading1'] 30 ['Enero',1000, 2000], img=Image("Tux2.png",width=80,
10 h1.pageBreakBefore=0 31 height=100)
11 h1.keepWithNext=1 ['Febrero',3000,100.5], 53 story.append(img)
12 h1.backColor=colors.red 32 ['Marzo',2000,1000], 54 doc=SimpleDocTemplate("para-
13 h2=styleSheet['Heading2'] 33 ['Abril',1500,1500]] grahp.pdf",pagesize=A4,showBou
14 h2.pageBreakBefore=0 34 ) ndary=1)
15 h2.keepWithNext=1 35 55 doc.build(story)

60 Número 13 WWW.LINUX- MAGAZINE.ES

También podría gustarte