在生成PDF报表时,往往需要动态的生成表格和一些折线图、饼状图等,利用RML文件和reportlab的api来动态生成。
表格
利用<blockTable>
和<blockTableStyle>
,生成有多种样式的表格,并通过内嵌python代码来动态的填充数据。
统计图
官网chart gallery 下有很多的统计图的举例,都有源码,地址为 https://www.reportlab.com/chartgallery/line/ ,展示了如何利用API构造生成一个统计图表的PDF。利用RML中的<drawing>
标签,在PDF中动态的添加统计图,参考RML Samples下的http://www.reportlab.com/examples/rml/test/test_014_graphics.pdf 。
* <drawing>
:通过查看Tag Reference发现该标签拥有module
和function
两个属性。module
所对应的即py的module,function
是该module下的类(或方法)。
* class DemoDrawing(_DrawingEditorMixin, Drawing)
:仿照官网的统计图的Demo,编写定义统计图Drawing的类。
* <param name=''>
:利用<drawing></drawing>
下的<param>
标签和其name
属性指定统计图所需参数,同时结合RML中的{
{}}
,动态的填充参数数据。
结合官网的QuickChart的Demo编写一个简单的生成统计图PDF的ChartDemo。
* 简单生成PDF工具类utils.py
:
from rlextra.rml2pdf import rml2pdf
import preppy
from io import BytesIO
class PDFUtils(object):
def __init__(self, template_name, namespace, output_filename=None):
self.template_name = template_name
self.namespace = namespace
self.output_filename = output_filename
def create_pdf(self):
source_text = open(self.template_name, 'r', encoding='utf-8').read()
template = preppy.getModule(self.template_name, sourcetext=source_text)
rml = template.getOutput(self.namespace)
if self.output_filename:
rml2pdf.go(rml.encode('utf-8'), outputFileName=self.output_filename)
return True
else:
buf = BytesIO()
rml2pdf.go(rml.encode('utf-8'), outputFileName=buf)
pdf_data = buf.getvalue()
return pdf_data
- 统计图Drawing类
charts_model.py
:该类利用QuickChart
快速生成了一个柱状图。
from rlextra.graphics.quickchart import QuickChart
from reportlab.lib.corp import white, black
from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin
class QuickDemoDrawing(_DrawingEditorMixin, Drawing):
def __init__(self, width=400, height=200, *args, **kw):
Drawing.__init__(self, width, height, *args, **kw)
self._add(self, QuickChart(), name='chart', validate=None, desc=None)
self.chart.x = 100
self.chart.y = 300
self.chart.height = 200
self.chart.seriesNames = 'a', 'b', 'c'
self.chart.seriesRelation = None
self.chart.dataLabelsFontSize = 12
self.chart.chartSeparation = 1
self.chart.data = [[100, 120, 140], [110, 130, 150], [200, 100, 100]]
self.chart.chartType = 'column'
self.chart.titleText = 'Column Chart'
self.chart.xTitleText = ''