pdfgen是生成PDF文档的最基本的方法。实际上就是一系列在canvas上绘制的指令。
canvas(画布)是带有坐标的页面,默认以“点”为单位,原点在左下角。以下是一个简单的示范:
# 生成一个写有"Hello World"的pdf
from reportlab.pdfgen import canvas
# 定义一个在pdf中写入字符的函数
def hello(c):
c.drawString(100,100,"Hello World")
# 字符的左边为(100, 100),即从页面左下角向上100点且向右100点开始
c= canvas.Canvas("hello.pdf")
# 创建pdf
hello(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()
# 保存文档
showPage
会停止对当前页的绘制,之后的任何指令都只会对下一页起作用。
canvas包含的属性可以从它的构造函数的参数得知:
def __int__(self, filename,
pagesize=(595.27,841.89),
bottomeup = 1,
pageCompression=0,
encoding=rl_config.defaultEncoding,
verbosity=0,
encrypt=None):
其中几个比较常用的:
filename
——在这里创建pdf并命名。pagesize
——定义页面尺寸;输入宽度和高度,就可以自定义页面尺寸;canvas默认的是A4的尺寸,除此之外reportlab还有很多自带的页面样式,比如下面的语句可以将页面尺寸设置为美国常用的letter尺寸:from reportlab.lib.pagesizes import letter, A4
myCanvas = Canvas('myfile.pdf', pagesize=letter)
bottomup
——将这个参数的值改为0就能把原点从左下角变成左上角。pageCompression
——是否压缩页面,0为不压缩,1为压缩。当文档比较大的时候就需要压缩,但是这个操作会比较费时间。将上面的创建pdf的代码修改如下:
from reportlab.pdfgen import canvas
def hello(c):
from reportlab.lib.units import inch
# 更改原点位置(向上和向右移动1英寸)
c. translate(inch,inch)
# 设置字体和字号
c.setFont("Helvetica", 14)
# 设置轮廓颜色
c.setStrokeColorRGB(0.2,0.5,0.3)
# 设置填充颜色
c.setFillColorRGB(1,0,1)
# 绘制线条
c.line(0,0,0,1.7*inch)
c.line(0,0,1*inch,0)
# 绘制矩形
c.rect(0.2*inch,0.2*inch,1*inch,1.5*inch, fill=1)
# 使文本逆时针旋转90度
c.rotate(90)
# 改变填充颜色
c.setFillColorRGB(0,0,0.77)
# 绘制字符串(旋转后,y坐标需要变成负数)
c.drawString(0.3*inch, -inch, "Hello World")
c= canvas.Canvas("hello.pdf")
hello(c)
c.showPage()
c.save()
上面的代码中包含了两种指令:
这里先列举一些绘制工具,后面的章节将详细介绍。
canvas.line(x1,y1,x2,y2)
canvas.lines(linelist)
canvas.grid(xlist, ylist)
canvas.bezier(x1, y1, x2, y2, x3, y3, x4, y4)
canvas.arc(x1,y1,x2,y2)
canvas.rect(x, y, width, height, stroke=1, fill=0)
canvas.ellipse(x1,y1, x2,y2, stroke=1, fill=0)
canvas.wedge(x1,y1, x2,y2, startAng, extent, stroke=1, fill=0)
canvas.circle(x_cen, y_cen, r, stroke=1, fill=0)
canvas.roundRect(x, y, width, height, radius, stroke=1, fill=0)
canvas.drawString(x, y, text):
canvas.drawRightString(x, y, text)
canvas.drawCentredString(x, y, text)
textobject = canvas.beginText(x, y)
canvas.drawText(textobject)
path = canvas.beginPath()
canvas.drawPath(path, stroke=1, fill=0, fillMode=None)
canvas.clipPath(path, stroke=1, fill=0, fillMode=None)
canvas.drawInlineImage(self, image, x,y, width=None,height=None)
canvas.drawImage(self, image, x,y, width=None,height=None,mask=None)
注意:图片插入需要配合PIL实现。
canvas.showPage()
注意:所有的属性设置(颜色、字体等)在这个语句后都会被重置。
canvas.setFillColorCMYK(c, m, y, k)
canvas.setStrikeColorCMYK(c, m, y, k)
canvas.setFillColorRGB(r, g, b)
canvas.setStrokeColorRGB(r, g, b)
canvas.setFillColor(acolor)
canvas.setStrokeColor(acolor)
canvas.setFillGray(gray)
canvas.setStrokeGray(gray)
canvas.setFont(psfontname, size, leading = None)
# leading参数设置行距
# 设置线条宽度
canvas.setLineWidth(width)
# 设置线条端点类型
canvas.setLineCap(mode)
# 设置线条联接类型
canvas.setLineJoin(mode)
canvas.setMiterLimit(limit)
canvas.setDash(self, array=[], phase=0)
# 设置页面尺寸
canvas.setPageSize(pair)
canvas.transform(a,b,c,d,e,f):
canvas.translate(dx, dy)
canvas.scale(x, y)
canvas.rotate(theta)
canvas.skew(alpha, beta)
这些设置时叠加的,也就是说新的设置会改变已有的设置但是不会替代它。
# 保存属性设置
canvas.saveState()
# 恢复属性设置
canvas.restoreState()
canvas.setAuthor()
canvas.addOutlineEntry(title, key, level=0, closed=None)
canvas.setTitle(title)
canvas.setSubject(subj)
canvas.pageHasData()
canvas.showOutline()
canvas.bookmarkPage(name)
canvas.bookmarkHorizontalAbsolute(name, yhorizontal)
canvas.doForm()
canvas.beginForm(name, lowerx=0, lowery=0, upperx=None, uppery=None)
canvas.endForm()
canvas.linkAbsolute(contents, destinationname, Rect=None, addtopage=1, name=None, **kw)
canvas.linkRect(contents, destinationname, Rect=None, addtopage=1, relative=1, name=None, **kw)
canvas.getPageNumber()
canvas.addLiteral()
canvas.getAvailableFonts()
canvas.stringWidth(self, text, fontName, fontSize, encoding=None)
canvas.setPageCompression(onoff=1)
canvas.setPageTransition(self, effectname=None, duration=1,
direction=0,dimension='H',motion='I')
下面的函数展示了如何在canvas中运用坐标来绘制:
from reportlab.pdfgen import canvas
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch,
1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
c= canvas.Canvas("coords.pdf")
# 创建pdf
coords(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()
translate
下面的函数展示了如何将原点移动至指定位置:
from reportlab.pdfgen import canvas
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch,
1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
# 新增的函数!!!!!
def translate(canvas):
# 导入cm作为单位,代替默认的单位——“点”
from reportlab.lib.units import cm
canvas.translate(2.3*cm, 0.3*cm)
coords(canvas)
c= canvas.Canvas("transcoords.pdf")
# 创建pdf
translate(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()
运用canvas.scale(dx,dy)
可以将坐标进行缩放,其中dx,dy
分别代表横纵坐标的缩放比例。例子如下:
from reportlab.pdfgen import canvas
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch,
1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
# 新增的函数!!!!!
def scale(canvas):
canvas.scale(0.75, 0.5)
coords(canvas)
c= canvas.Canvas("scale.pdf")
# 创建pdf
scale(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()
将其与上面的coords
函数结合效果如下图:
坐标缩放、原点移动和其他属性设置可以结合使用,但是要注意两个指令的先后顺序。比如下面这个例子:
from reportlab.pdfgen import canvas
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch,
1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
# 新增的函数!!!!!
def scaletranslate(canvas):
from reportlab.lib.units import inch
canvas.setFont("Courier-BoldOblique", 12)
# 保存属性设置
canvas.saveState()
# 先缩放再改变坐标原点
canvas.scale(0.3, 0.5)
canvas.translate(2.4*inch, 1.5*inch)
canvas.drawString(0, 2.7*inch, "Scale then translate")
coords(canvas)
# 恢复属性设置后,之前的缩放和原点移动都将重置
canvas.restoreState()
# 先改变坐标原点再缩放
canvas.translate(2.4*inch, 1.5*inch)
canvas.scale(0.3, 0.5)
canvas.drawString(0, 2.7*inch, "Translate then scale")
coords(canvas)
c= canvas.Canvas("scaletranslate.pdf")
# 创建pdf
scaletranslate(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()
将其与coords
函数结合效果如下:
因为缩放之后坐标的比例会改变,同样的参数移动原点的结果会不一样。
上面的例子也一并展示了如何运用属性保存和恢复,即saveState
和restoreState
这个方法可能并不常用,但是很有趣。它没有专门的函数,但是可以运用translate
和scale
来实现,例子如下:
from reportlab.pdfgen import canvas
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch,
1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
# 新增的函数!!!!!
def mirror(canvas):
from reportlab.lib.units import inch
canvas.translate(5.5*inch, 0)
canvas.scale(-1.0, 1.0)
coords(canvas)
c= canvas.Canvas("mirror.pdf")
# 创建pdf
mirror(c)
# 引用刚定义的函数
c.showPage() # 保存当前页
c.save()