如何使用pdfrw设置图像在reportlab中的位置?

时间:2019-05-24 12:54:20

标签: python pdf-generation reportlab pdfrw

我正在使用reportlab生成报告。我可以通过四个步骤定义创建过程:1)通过API获取数据,2)过滤数据,3)使用matplotlib生成图形,以及4)使用reportlab在PDF中插入信息。 / p>

我在this(感谢Patrick Maupin!)和this(感谢Larry Meyn!)中找到了flowable matplotlib的答案{ {1}}。我进行了一些更改,并在下面的代码部分中进行了复制:

ReportLab

我的问题出在import os from matplotlib import pyplot as plt from matplotlib.backends.backend_pdf import PdfPages from reportlab.platypus import Paragraph, SimpleDocTemplate, Flowable from reportlab.lib.styles import getSampleStyleSheet from reportlab.pdfbase import pdfmetrics from reportlab.pdfgen import canvas from pdfrw import PdfReader, PdfDict from pdfrw.buildxobj import pagexobj from pdfrw.toreportlab import makerl try: from cStringIO import StringIO as BytesIO except ImportError: from io import BytesIO styles = getSampleStyleSheet() style = styles['Normal'] #Info if you want to run the script div = ['may/18', 'jun/18', 'jul/18', 'aug/18', 'sep/18', 'oct/18', 'nov/18', \ 'dec/18', 'jan/19', 'feb/19', 'mar/19', 'apr/19'] mes = [0, 15, 149, 0, 59, 0, 0, 101, 45, 25, 751.07, 5358.3] acc = [0, 15, 164, 164, 223, 223, 223, 324, 369, 394, 1145.07, 6503.37] class PdfImage(Flowable): """ Generates a reportlab image flowable for matplotlib figures. It is initialized with either a matplotlib figure or a pointer to a list of pagexobj objects and an index for the pagexobj to be used. """ def __init__(self, fig=None, width=200, height=200, cache=None, cacheindex=0): self.img_width = width self.img_height = height if fig is None and cache is None: raise ValueError("Either 'fig' or 'cache' must be provided") if fig is not None: imgdata = BytesIO() fig.savefig(imgdata, format='pdf') imgdata.seek(0) page, = PdfReader(imgdata).pages image = pagexobj(page) self.img_data = image else: self.img_data = None self.cache = cache self.cacheindex = cacheindex def wrap(self, width, height): return self.img_width, self.img_height def drawOn(self, canv, x, y, _sW=0): if _sW > 0 and hasattr(self, 'hAlign'): a = self.hAlign if a in ('CENTER', 'CENTRE', TA_CENTER): x += 0.5*_sW elif a in ('RIGHT', TA_RIGHT): x += _sW elif a not in ('LEFT', TA_LEFT): raise ValueError("Bad hAlign value " + str(a)) canv.saveState() if self.img_data is not None: img = self.img_data else: img = self.cache[self.cacheindex] if isinstance(img, PdfDict): xscale = self.img_width / img.BBox[2] yscale = self.img_height / img.BBox[3] canv.translate(x, y) canv.scale(xscale, yscale) canv.doForm(makerl(canv, img)) else: canv.drawImage(img, x, y, self.img_width, self.img_height) canv.restoreState() class PdfImageCache(object): """ Saves matplotlib figures to a temporary multi-page PDF file using the 'savefig' method. When closed the images are extracted and saved to the attribute 'cache'. The temporary PDF file is then deleted. The 'savefig' returns a PdfImage object with a pointer to the 'cache' list and an index for the figure. Use of this cache reduces duplicated resources in the reportlab generated PDF file. Use is similar to matplotlib's PdfPages object. When not used as a context manager, the 'close()' method must be explictly called before the reportlab document is built. """ def __init__(self): self.pdftempfile = '_temporary_pdf_image_cache_.pdf' self.pdf = PdfPages(self.pdftempfile) self.cache = [] self.count = 0 def __enter__(self): return self def __exit__(self, *args): self.close() def close(self, *args): self.pdf.close() pages = PdfReader(self.pdftempfile).pages pages = [pagexobj(x) for x in pages] self.cache.extend(pages) os.remove(self.pdftempfile) def savefig(self, fig, width=200, height=200): self.pdf.savefig(fig) index = self.count self.count += 1 return PdfImage(width=width, height=height, cache=self.cache, cacheindex=index) def make_report_cached_figs(outfn): """ Makes a dummy report with nfig matplotlib plots using PdfImageCache to reduce PDF file size. """ doc = SimpleDocTemplate(outfn) style = styles["Normal"] story = [] with PdfImageCache() as pdfcache: fig = plt.figure(figsize=(5, 5)) plt.bar(div, acc, width = 0.8, color = 'silver', label = 'Year') plt.bar(div, mes, width = 0.4, color = 'k', label = 'Month', alpha = 0.5) plt.legend() plt.xticks(rotation=60) plt.close() img0 = pdfcache.savefig(fig, width=185, height=135) img0.drawOn(doc, 0, 100) story.append(img0) doc.build(story) make_report_cached_figs("Test.pdf") 方法中,更具体地说,在第一个参数中。在上面的代码中,我得到以下错误:

drawOn

如果我将AttributeError: 'SimpleDocTemplate' object has no attribute 'saveState' 替换为doc = SimpleDocTemplate(outfn)(我知道如果我要使用doc = canvas.Canvas(outfn),则应该做一些其他小的更改),我会遇到另一个错误:

canvas

我已经在官方文档和源代码中搜索了信息,但未成功。因此,如何设置图像的位置?(是否使用img = self.cache[self.cacheindex] IndexError: list index out of range 方法)

0 个答案:

没有答案