我有以下代码尝试从CSV文件创建字典,然后将CSV中每个“行”的值附加到PDF中的新页面。我正在使用pyPdf和ReportLab来实现这一目标。
源PDF包含2页,明信片的正面和背面,我试图为CSV文件中的每条记录复制。例如,包含25条记录的CSV文件将生成包含50页的PDF。 (每个记录一个前面和一个后面)
我已经成功创建了具有适当页数的PDF,但是,我的代码中用于附加CSV文件中的值的部分为每个页面添加相同的值,而不是唯一值每页。
我很确定这与循环有关,因为打印字典会正确返回所有键和值对。我在这做错了什么?
d = {}
csv_file = open(filename, 'rb')
reader = csv.reader(csv_file)
rownum = 0
for row in reader:
total_rows += 1
page_count = (total_rows - 1)
if rownum == 0:
header = row
else:
colnum = 0
for col in row:
d[header[colnum]] = col
colnum += 1
packet = StringIO.StringIO()
can = canvas.Canvas(packet, pagesize=(621,405))
can.drawString(340, 147, d['FirstName'])
can.save()
packet.seek(0)
new_pdf = PdfFileReader(packet)
existing_pdf = PdfFileReader(file(order, 'rb'))
output = PdfFileWriter()
front = existing_pdf.getPage(0)
back = existing_pdf.getPage(1)
back.mergePage(new_pdf.getPage(0))
for i in range(0, page_count):
output.addPage(front)
output.addPage(back)
outputStream = file(token+'_merged.pdf', 'wb')
output.write(outputStream)
outputStream.close()
rownum += 1
答案 0 :(得分:1)
此循环为CSV中的每一行创建一个新文件,覆盖为早期行创建的版本。我并不完全熟悉您正在使用的库,但它看起来像是一种方法,可以在主循环外部保存outputStream
来修复它:
output = PdfFileWriter()
for rownum, row in enumerate(reader):
if rownum == 0:
header = row
else:
for col in row:
d[header[colnum]] = col
colnum += 1
# or, more concisely:
# d = dict((header[colnum], value) for (colnum, value) in enumerate(row))
# or use a dict comprehension if you're on a sufficiently recent version
# or best of all, use a csv.DictReader object instead of creating the dictionary yourself
packet = StringIO.StringIO()
can = canvas.Canvas(packet, pagesize=(621,405))
can.drawString(340, 147, d['FirstName'])
can.save()
packet.seek(0)
new_pdf = PdfFileReader(packet)
# I would check whether this can be read once and still have getPage called multiple times
existing_pdf = PdfFileReader(file(order, 'rb'))
front = existing_pdf.getPage(0)
back = existing_pdf.getPage(1)
back.mergePage(new_pdf.getPage(0))
output.addPage(front)
output.addPage(back)
outputStream = file(token+'_merged.pdf', 'wb')
output.write(outputStream)
outputStream.close()