Python reportlab

基本概念

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

canvas包含的属性可以从它的构造函数的参数得知:

def __int__(self, filename,
			pagesize=(595.27,841.89),
			bottomeup = 1,
			pageCompression=0,
			encoding=rl_config.defaultEncoding,
			verbosity=0,
			encrypt=None):

其中几个比较常用的:

  1. filename——在这里创建pdf并命名
  2. pagesize——定义页面尺寸;输入宽度和高度,就可以自定义页面尺寸;canvas默认的是A4的尺寸,除此之外reportlab还有很多自带的页面样式,比如下面的语句可以将页面尺寸设置为美国常用的letter尺寸:
from reportlab.lib.pagesizes import letter, A4
myCanvas = Canvas('myfile.pdf', pagesize=letter)
  1. bottomup——将这个参数的值改为0就能把原点从左下角变成左上角。
  2. 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()

上面的代码中包含了两种指令:

  1. 绘制指令:包括绘制线条、矩形和字符串。
  2. 属性指令:包括改变轮廓和填充颜色、字体以及字号等。

代码运行结果如下:
在pdf中绘制图形和文本

绘制工具

这里先列举一些绘制工具,后面的章节将详细介绍。

  • 线条绘制
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工具

 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函数结合效果如下:
缩放和改变原点的顺序
因为缩放之后坐标的比例会改变,同样的参数移动原点的结果会不一样。
上面的例子也一并展示了如何运用属性保存和恢复,即saveStaterestoreState

镜像

这个方法可能并不常用,但是很有趣。它没有专门的函数,但是可以运用translatescale来实现,例子如下:

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()

coords函数结合的效果如下:
镜像

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值