Reportlab生成PDF文件

这个折线图:

  • 不同样式虚线做数据线:chart.lines[i].strokeDashArray

  • 虚线截小段做图例的色块:

LineLegend,legend.colorNamePairs = Auto(obj = chart)

  • y轴将给的数据放大1000倍:chart.yValueAxis.labelTextScale

  • x轴刻度标签旋转90度:chart.xValueAxis.labels.angle

  • 设定x轴上标签的显示格式:

         chart.yValueAxis.labelTextFormat

代码及注释:

# 不同样式的数据折线以及指定坐标轴上标签的数据格式
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.lib.colors import PCMYKColor
from reportlab.graphics.charts.legends import LineLegend
from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, Line
from reportlab.lib.validators import Auto
from reportlab.lib.styles import black
from reportlab.graphics.charts.axes import XValueAxis, YValueAxis, AdjYValueAxis, NormalDateXValueAxis

class LineChart_DashedLinesNumberFormates(_DrawingEditorMixin,Drawing):
    def __init__(self,width=558,height=140,*args,**kw):
        Drawing.__init__(self,width,height,*args,**kw)

        # 公共变量
        fontName = 'Helvetica'      # 字体
        strokeWidth = 0.5           # 线宽
        dashArray = (0.3,1)         # 虚线样式
        lineCap = 1                 # 线头样式:0尖头、1圆头、2方头
        overShoot = 7.5             # 超出部分

        # 添加折线图表
        self._add(self,LinePlot(),name='chart',validate=None,desc=None)

        # 设置x坐标轴
        self.chart.xValueAxis = NormalDateXValueAxis()
        # x轴是个日期轴
        self.chart.xValueAxis.labels.fontName       = fontName
        # 日期轴上标签字体
        self.chart.xValueAxis.labels.fontSize       = 6
        # 日期轴上标签大小
        self.chart.xValueAxis.labels.boxAnchor      ='autox'
        # 锚点,默认是'n';'autox'能找到的资料仅一条,说是自适应标签框
        self.chart.xValueAxis.labels.angle          = 90
        # 标签旋转90度
        self.chart.xValueAxis.labels.rightPadding   = 2
        # 标签框的右留白
        self.chart.xValueAxis.xLabelFormat          = '{mm}/{dd}/{yy}'
        # 标签上的日期格式:月/日/年
        self.chart.xValueAxis.strokeDashArray       = dashArray
        # x轴和x轴上刻度线的样式,但似乎日期线不受约束
        self.chart.xValueAxis.strokeLineCap         = lineCap
        # 线头样式
        self.chart.xValueAxis.strokeWidth = 0.5
        # 线的宽度
        self.chart.xValueAxis.maximumTicks          = 20
        # 刻度可以有的最大个数
        self.chart.xValueAxis.forceFirstDate        = 1
        # 显示数据中的第一个日期
        self.chart.xValueAxis.forceEndDate          = 1
        # 显示最后一个日期
        self.chart.xValueAxis.dailyFreq             = 0
        # 为真时数轴上的刻度是每月最后一天
        self.chart.xValueAxis.minimumTickSpacing    = 15
        # 刻度间距离的最小值
        self.chart.xValueAxis.visible = 1
        # x轴可见
        self.chart.xValueAxis.visibleGrid = 0
        # x轴上的刻度格线不可见
        self.chart.xValueAxis.gridStrokeWidth = 0.25
        # 如果有刻度格线的话刻度线的宽度
        self.chart.xValueAxis.visibleTicks = 1
        # x轴上的刻度可见

        # y axis
        self.chart.yValueAxis.labels.fontName       = fontName
        # y轴上的标签字体
        self.chart.yValueAxis.labels.fontSize       = 6
        # y轴上的标签字体大小
        self.chart.yValueAxis.labelTextFormat       = '$%0.2f'
        # y轴上标签格式,前面加一个$,小数点后两位数字的实数
        self.chart.yValueAxis.labels.rightPadding   = 7
        # 标签右留白
        self.chart.yValueAxis.strokeWidth           = 0.5
        # y轴线宽
        self.chart.yValueAxis.strokeDashArray = dashArray
        # y轴线的样式
        self.chart.yValueAxis.strokeLineCap         = lineCap
        # 线头样式
        self.chart.yValueAxis.maximumTicks          = 15
        self.chart.yValueAxis.rangeRound            ='both'
        # OneOf('none','both','ceiling','floor'),'How to round the axis limits'
        # 刻度的最高最低怎么取,ceiling是进最近的那个最大的,floor是最近的那个最小的
        self.chart.yValueAxis.avoidBoundFrac        = 0.1
        # 间隔、最上和最下都受这个值的影响,可以切换成其他值感受一下它的影响
        # 源代码上的注释:Fraction of interval to allow above and below.
        # self.chart.yValueAxis.avoidBoundFrac        = 1
        # self.chart.yValueAxis.avoidBoundFrac        = 2
        # self.chart.yValueAxis.avoidBoundFrac        = 3
        # self.chart.yValueAxis.avoidBoundFrac        = 5

        self.chart.yValueAxis.visibleGrid           = 1
        # 显示y轴上的刻度格线,接着设定刻度格线的宽度、样式和线头
        self.chart.yValueAxis.gridStrokeWidth       = strokeWidth
        self.chart.yValueAxis.gridStrokeDashArray   = dashArray
        self.chart.yValueAxis.gridStrokeLineCap     = lineCap

        self.chart.yValueAxis.visibleAxis           = 1
        # 显示y轴

        self.chart.yValueAxis.labelTextScale          = 1000
        # 将y值扩大1000倍标在y坐标轴上
        self.chart.yValueAxis.tickLeft                = 0
        # 刻度线左伸出为0

        # legend
        self._add(self,LineLegend(),name='legend',validate=None,desc=None)
        self.legend.colorNamePairs   =  Auto(obj=self.chart)
        # 图例开启自动模式,用数据线上的一小段做色块,一一对应chart.lines各数据线的名字name属性
        self.legend.fontName         = fontName
        self.legend.fontSize         = 7
        self.legend.alignment        ='right'
        # 文字在色块右边
        self.legend.columnMaximum    = 1
        # 每列最多一行
        self.legend.dxTextSpace      = 5
        # 文字与色块的距离
        self.legend.variColumn       = 1
        # 列宽可变
        self.legend.autoXPadding     = 15
        # deltax=None时,x方向的列间留白

        # 折线上的数据列表,包括三个元素列表,每个元素列表里包括一组数据
        # 三组数据三条数据线
        self.chart.data = [[(20070201, 1.0), (20070228, 1.0089999999999999), (20070331, 1.0264), (20070430, 1.0430999999999999), (20070531, 1.0649), (20070630, 1.0720000000000001), (20070731, 1.0742), (20070831, 1.0553999999999999), (20070930, 1.0713999999999999), (20071031, 1.1031), (20071130, 1.093), (20071231, 1.1005), (20080131, 1.0740000000000001)],
                           [(20070201, 1.0), (20070228, 1.0154000000000001), (20070331, 1.0155000000000001), (20070430, 1.0208999999999999), (20070531, 1.0132000000000001), (20070630, 1.0101), (20070731, 1.0185), (20070831, 1.0309999999999999), (20070930, 1.0388999999999999), (20071031, 1.0482), (20071130, 1.0670999999999999), (20071231, 1.0701000000000001), (20080131, 1.0880000000000001)],
                           [(20070201, 1.0), (20070228, 1.0089999999999999), (20070331, 1.0182), (20070430, 1.0311999999999999), (20070531, 1.0471999999999999), (20070630, 1.0518000000000001), (20070731, 1.0532999999999999), (20070831, 1.0344), (20070930, 1.0470999999999999), (20071031, 1.0699000000000001), (20071130, 1.0613999999999999), (20071231, 1.0621), (20080131, 1.0455000000000001)]]

        # 颜色列表
        self._colorsList = [PCMYKColor(23,51,0,4), PCMYKColor(66,13,0,22), PCMYKColor(100,60,0,50), PCMYKColor(0,0,0,0),PCMYKColor(0,0,0,0),PCMYKColor(0,0,0,0)]
        # 直线样式列表
        self._dashArray = [(1, 1), (6, 2), (2, 2, 2, 2, 10), ]
        # 数据线所代表的名字列表
        self._sNames = 'Liberty International', 'Persimmon', 'Royal Bank of Scotland',

        # 依次赋值给每条数据线对应的属性:名字、颜色和直线样式
        for i in range(len(self.chart.data)):
            self.chart.lines[i].name = self._sNames[i]  # 数据线代表啥
            self.chart.lines[i].strokeColor = self._colorsList[i]
            # 数据线颜色
            self.chart.lines[i].strokeDashArray = self._dashArray[i]
            # 数据线样式
        self.chart.lines.strokeWidth         = 2    # 数据线宽度

        # 重新调整画板大小、图表坐标、图表宽高和图例坐标
        self.width       = 400
        self.height      = 200
        self.chart.x               = 50
        self.chart.y               = 50
        self.chart.width           = 300
        self.chart.height          = 100
        self.legend.y              = 175
        self.legend.x              = 100

        # 图表上左、右、底部各加一条直线
        self._add(self, Line(self.chart.x, self.chart.y, self.chart.x, self.chart.y + self.chart.height,
                             strokeWidth=strokeWidth, strokeDashArray=dashArray, strokeLineCap=lineCap), name='L0')
        self._add(self, Line(self.chart.x + self.chart.width, self.chart.y, self.chart.x + self.chart.width,
                             self.chart.y + self.chart.height, strokeWidth=strokeWidth, strokeDashArray=dashArray,
                             strokeLineCap=lineCap), name='L1', validate=None, desc=None)
        self._add(self, Line(self.chart.x - overShoot, self.chart.y, self.chart.x + self.chart.width + overShoot,
                             self.chart.y, strokeWidth=strokeWidth), name='L2', validate=None, desc=None)

        # 底部直线左右多出一块,调整一下
        self.L2.x1               = 50
        self.L2.x2               = 350
        self.L2.y1               = 50
        self.L2.y2               = 50

        # 调整线条宽度
        self.L0.strokeWidth      = 1
        self.L1.strokeWidth      = 1
        self.L2.strokeWidth      = 0.75

if __name__=="__main__": #NORUNTESTS
    LineChart_DashedLinesNumberFormates().save(formats=['pdf'],outDir='.',fnRoot=None)