Reportlab生成PDF文件

单词annotation是解释、注释的意思,图表属性annotation可以通过三个参数带我们“深入”图表内部做些“注释”的工作,来看annotation的典型赋值:

chart.annotations=[lambda c,cA,vA: Line(c.x,vA(0),c.x+c.width,vA(0),strokeColor=red,strokeWidth=strokeWidth)]

chart是图表对象,赋给annotations的值是个列表,列表内是lambda表达式,定义了一个匿名函数。

lambda是个令人困惑的存在,所以来看一个lambda的使用例子。先来定义一个函数,功能是把传过来的参数加1后打印出来:

def f(x):
    print(x+1)
f(3)

运行结果是4。

用lambda定义同样功能的函数然后调用,结果同直接定义函数:

f = lambda x: print(x+1)
f(3)

关键字lambda后是入口参数x,行参后跟着冒号,然后是函数体print(x+1)。有位叫做Goodpy的博主总结说:lambda是为了减少单行函数的定义而存在。

回到annotation赋值的lambda表达式:

lambda c,cA,vA: Line(c.x,vA(0),c.x+c.width,vA(0),strokeColor=red,strokeWidth=strokeWidth)

这个表达式是画一条直线,坐标轴原点出发的x轴。

关键字lambda后跟着三个行参,使用时带入执行的三个实参分别是:c, xscale, yscale,c是图表本身,xscale是x轴上的刻度,yscale是y轴上的刻度。

xscale是x轴上的刻度怎么解释?

  • x轴是类别轴(categoryAxis),xscale(3)是个元组:

    xscale(3)[0]是x轴上第3个刻度的x坐标;xscale(3)[1]是x轴上刻度之间的距离。

  • x轴是数值轴(valueAxis),xscale(3)是个元组:

    xscale(3)[0]是x轴上刻度3的x坐标;xscale(3)[1]是x轴上刻度之间的距离。

  • x轴是日期轴(NormalDateXValueAxis):

    xscale(NormalDate(20050131))是日期20050131在日期轴上的x坐标。

    from reportlab.lib.normalDate import NormalDate

    NormalDate(20050131)或NormalDate(‘20050131’)是2005年1月31日在日期轴上的刻度。

yscale是y轴上的刻度怎么解释?

y轴一般是数值轴(valueAxis),yscale(3)是y轴上刻度3的y坐标。

再来看直线起点坐标,(c.x,vA(0))和终点坐标(c.x+c.width,vA(0)),这里y轴是数值轴。c.x是图表左下角的x坐标,vA(0)是y轴上0刻度的y坐标,c.width是图表的宽度。

如果想再加一条直线怎么办?之前对chart.annotations的赋值是个列表,所以用列表的chart.annotations.extend()或chart.annotations.append()方法函数皆可,extend()给的参数是列表,即把其他列表的元素收进来,append()给的参数是要收进来的元素。

接下来用annotation属性在图表中加两条红色的线并打印出图表坐标和坐标原点坐标:

三条annotation的语句:

self.chart.annotations=[lambda c,cA,vA: Line(c.x,vA(0),c.x+c.width,vA(0),strokeColor=red,strokeWidth=strokeWidth)]
# 横着的红线
self.chart.annotations.extend([lambda c,cA,vA: Line(cA(2)[0],c.y-tickOut,cA(2)[0],c.y+c.height+gridStickOut,strokeColor=red,strokeWidth=strokeWidth)])
# 竖着的红线
self.chart.annotations.extend([lambda c,cA,vA: print('图表左下角坐标:({},{})\n坐标原点:({},{})'.format(c.x, c.y, cA(0)[0], vA(0)))])
# 输出坐标

输出的坐标:

图表左下角坐标:(24,54)

坐标原点:(24.0,95.66666666666667)