使用ReportLab批量生成条形码

时间:2018-08-10 15:02:32

标签: python python-3.x pdf reportlab

Yesterday, I asked a question that was perhaps too broad.

今天,我已按照自己的想法采取行动,以实施解决方案。

我使用ReportLabpdfqueryPyPDF2来自动化在PDF文档中数百页上生成条形码的过程。

每页需要一个条形码。但是,如果页面的右上角有一个字母(“ A”至“ E”),则它需要使用与上一页相同的条形码。右上角带有字母的文件是具有类似信息的重复形式。

如果没有字母,则应在该页面上使用唯一的条形码编号(增加一个即可)。

我的代码似乎可以正常工作,但是我遇到两个问题:

  1. 条形码移动的幅度很小(次要问题)。
  2. 条形码值不会改变(主要问题)。在所有页面上仅设置第一个条形码编号。

我似乎无法说出为什么价值没有变化。有人有线索吗?

代码在这里:

import pdfquery
import os
from io import BytesIO
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.graphics.barcode import eanbc
from reportlab.graphics.shapes import Drawing 
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.graphics import renderPDF

pdf = pdfquery.PDFQuery("letters-test.pdf")

total_pages = pdf.doc.catalog['Pages'].resolve()['Count']
print("Total pages", total_pages)

barcode_value = 12345670

output = PdfFileWriter()

for i in range(0, total_pages):
    pdf.load(i) # Load page i into memory
    duplicate_letter = pdf.pq('LTTextLineHorizontal:in_bbox("432,720,612,820")').text()

    if duplicate_letter != '':
        print("Page " + str(i+1) + " letter " + str(duplicate_letter))
        print(barcode_value)
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=letter)

        # draw the eanbc8 code
        barcode_eanbc8 = eanbc.Ean8BarcodeWidget(str(barcode_value))
        bounds = barcode_eanbc8.getBounds()
        width = bounds[2] - bounds[0]
        height = bounds[3] - bounds[1]
        d = Drawing(50, 10)
        d.add(barcode_eanbc8)
        renderPDF.draw(d, c, 400, 700)
        c.save()

        packet.seek(0)

        new_pdf = PdfFileReader(packet)

        # read existing PDF
        existing_pdf = PdfFileReader(open("letters-test.pdf", "rb"))

        # add the "watermark" (which is the new pdf) on the existing page
        page = existing_pdf.getPage(i)
        page.mergePage(new_pdf.getPage(0))
        output.addPage(page)

    else:
        # increment barcode value
        barcode_value += 1
        print("Page " + str(i+1) + " isn't a duplicate.")
        print(barcode_value)
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=letter)

        # draw the eanbc8 code
        barcode_eanbc8 = eanbc.Ean8BarcodeWidget(str(barcode_value))
        bounds = barcode_eanbc8.getBounds()
        width = bounds[2] - bounds[0]
        height = bounds[3] - bounds[1]
        d = Drawing(50, 10)
        d.add(barcode_eanbc8)
        renderPDF.draw(d, c, 420, 710)
        c.save()

        packet.seek(0)

        new_pdf = PdfFileReader(packet)

        # read existing PDF
        existing_pdf = PdfFileReader(open("letters-test.pdf", "rb"))

        # add the "watermark" (which is the new pdf) on the existing page

        page = existing_pdf.getPage(i)
        page.mergePage(new_pdf.getPage(0))
        output.addPage(page)

     # Clear page i from memory and re load.
     # pdf = pdfquery.PDFQuery("letters-test.pdf")


outputStream = open("newpdf.pdf", "wb")
output.write(outputStream)
outputStream.close()

And here is letters-test.pdf

2 个答案:

答案 0 :(得分:3)

正如卡米尔·尼克(Kamil Nicki)的答案所指出的,Ean8BarcodeWidget limiting effective digits to 7

class Ean8BarcodeWidget(Ean13BarcodeWidget):
    _digits=7
...
self.value=max(self._digits-len(value),0)*'0'+value[:self._digits]

您可以更改编码方案,或将EAN 13条形码与Ean13BarcodeWidget配合使用,该条形码可以使用12位数字。

答案 1 :(得分:2)

条形码不变的原因是您在eanbc.Ean8BarcodeWidget中提供了太长的整数。

根据EAN标准,EAN-8条形码的长度为8位(7位+校验位)

解决方案:

如果将barcode_value12345670更改为1234560并运行脚本,您会看到条形码值随需要而增加,并且校验位被追加为第八位。

掌握这些信息后,您只应使用7位数字即可将信息编码为条形码。