简体   繁体   English

使用ReportLab批量生成条形码

[英]Batch generating barcodes using ReportLab

Yesterday, I asked a question that was perhaps too broad. 昨天,我问了一个可能过于宽泛的问题。

Today, I've acted on my ideas in an effort to implement a solution. 今天,我已经采取行动,努力实施解决方案。

Using ReportLab , pdfquery and PyPDF2 , I'm trying to automate the process of generating barcodes on hundreds of pages in a PDF document. 使用ReportLabpdfqueryPyPDF2 ,我正在尝试自动化在PDF文档中的数百页上生成条形码的过程。

Each page needs to have one barcode. 每个页面都需要一个条形码。 However, if a page has a letter in the top right ('A' through 'E') then it needs to use the same barcode as the previous page. 但是,如果页面右上角有一个字母('A'到'E'),那么它需要使用与上一页相同的条形码。 The files with letters on the top right are duplicate forms with similar information. 右上角带有字母的文件是具有类似信息的重复表单。

If there is no letter present, then a unique barcode number (incremented by one is fine) should be used on that page. 如果没有字母存在,则应在该页面上使用唯一的条形码编号(加1加罚款)。

My code seems to work, but I'm having two issues: 我的代码似乎有用,但我有两个问题:

  1. The barcode moves around ever so slightly (minor issue). 条形码移动得如此轻微(小问题)。
  2. The barcode value will not change (major issue). 条形码值不会改变(主要问题)。 Only the first barcode number is set on all pages. 仅在所有页面上设置第一个条形码编号。

I can't seem to tell why the value isn't changing. 我似乎无法分辨为什么价值不会改变。 Does anyone have an a clue? 有没有人有线索?

Code is here: 代码在这里:

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 这里是letters-test.pdf

as Kamil Nicki's answer pointed out, Ean8BarcodeWidget limiting effective digits to 7 : 正如Kamil Nicki的回答指出的那样, Ean8BarcodeWidget将有效数字限制为7

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

you may change your encoding scheme or use EAN 13 barcode with Ean13BarcodeWidget , which has 12 digits usable. 您可以更改您的编码方案或使用Ean13BarcodeWidget EAN 13条形码,它可以使用12位数字。

The reason why your barcode is not changing is that you provided too long integer into eanbc.Ean8BarcodeWidget . 条形码没有变化的原因是你在eanbc.Ean8BarcodeWidget提供了太长的整数。

According to EAN standard EAN-8 barcodes are 8 digits long (7 digits + checkdigit) 根据EAN标准,EAN-8条形码长度为8位(7位数+校验位)

Solution: 解:

If you change barcode_value from 12345670 to 1234560 and run your script you will see that barcode value is increased as you want and checkdigit is appended as eighth number. 如果更改barcode_value123456701234560和运行脚本,你将看到你想要的条形码值增加和校验码被追加为第八号。

With that information in hand you should use only 7 digits to encode information in barcode. 有了这些信息,您应该只使用7位数字来编码条形码中的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM