【问题标题】:Writing full csv table to PDF in Python在 Python 中将完整的 csv 表写入 PDF
【发布时间】:2018-02-19 09:53:24
【问题描述】:

我有一个 python 脚本,它使用 reportlab platypus 将文本消息数据从 .csv 文件写入 PDF 中的表格。它只将表格的最后一行写入单元格。它忽略此点之前的所有其他行。它写入 PDF 的唯一行是 excel 片段中以黄色突出显示的最后一行。如图所示,还包括一个 sn-p 将其写入 PDF 时的外观。

它还会在三页或四页中创建 PDF,推断它正在尝试为整个表格腾出空间,但不会写入。这是我迄今为止一直在使用的代码。我想以 Excel sn-p 中显示的相同格式将其写入 PDF 文档。我应该如何重构我的代码来做到这一点?

# Script to generate a PDF report after data has been parsed into smsInfo.csv file

# import statements
import requests
from reportlab.lib import colors
from reportlab.lib.pagesizes import *
from reportlab.platypus import *
from reportlab.lib.styles import getSampleStyleSheet
import csv
import os
import datetime

now = datetime.datetime.now()

# Get de work directory
cwd = os.getcwd()

# Introduction text
line1 = 'LYIT MOBILE FORENSICS DIVISION'
line2 = 'Date: ' + now.strftime("%d-%m-%y")
line3 = 'Case Number: 10'
line4 = 'This forensic report on sms card data has been compiled by the forensic'
line5 = 'examiner in conclusion to the investigation into the RTA'
line6 = 'case which occurred on 23/01/2018.'


#PDF document layout
table_style = TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),
                       ('TEXTCOLOR',(1,1),(-2,-2),colors.red),
                       ('VALIGN',(0,0),(0,-1),'TOP'),
                       ('TEXTCOLOR',(0,0),(0,-1),colors.blue),
                       ('ALIGN',(0,-1),(-1,-1),'CENTER'),
                       ('VALIGN',(0,-1),(-1,-1),'MIDDLE'),
                       ('TEXTCOLOR',(0,-1),(-1,-1),colors.green),
                       ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                       ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                       ])
styles = getSampleStyleSheet()
styleNormal = styles['Normal']
styleHeading = styles['Heading1']
styleHeading2 = styles['Heading2']
styleHeading.alignment = 1 # centre text (TA_CENTRE)

#Configure style and word wrap
s = getSampleStyleSheet()
s = s["BodyText"]
s.wordWrap = 'CJK'

# File that must be written to report
with open('H:\College Fourth Year\Development Project\Final Year Project 2018\ExtractedEvidence\smsInfo.csv', "r") as csvfile:
    reader = csv.reader(csvfile)
    lista = list(reader)

headers = lista[0]

conteo = 1

for numRecord in range(1,len(lista)):

    record1 = lista[numRecord]

    data = list()
    emptyRecords = list()
    records = list()
    header = list()

    countRecords = 0

    for line in record1:

        if line == '':
            emptyRecords.append(line)
        else:
            records.append(line)
            header.append(headers[countRecords])

            data.append([str(headers[countRecords]), str(line)])

        countRecords = countRecords + 1

    data2 = [[Paragraph(cell, s) for cell in row] for row in data]
    t = Table(data2)
    t.setStyle(table_style)

    elements = []

    # Name of file
    fileName = cwd + '\\' + 'Forensic Reports\\SMS Data Report' + '.pdf'

    conteo = conteo + 1

    archivo_pdf = SimpleDocTemplate(fileName, pagesize = letter, rightMargin = 40, leftMargin = 40, topMargin = 40, bottomMargin = 28)

    #Send the data and build the file
    elements.append(Paragraph(line1, styleNormal))
    elements.append(Paragraph(line2, styleNormal))
    elements.append(Paragraph(line3, styleNormal))
    elements.append(Spacer(inch, .25*inch))
    elements.append(Paragraph(line4, styleNormal))
    elements.append(Paragraph(line5, styleNormal))
    elements.append(Paragraph(line6, styleNormal))
    elements.append(Spacer(inch, .25*inch))
    elements.append(t)

    archivo_pdf.build(elements)
    print ('SMS Data Forensic Report Generated!')

【问题讨论】:

  • 从头开始。如果您print 数据,是否所有行都显示在您的控制台上?
  • 没有。我没有打印到控制台,而是将其打印到 PDF。
  • 我会打印到控制台检查输出
  • 它只打印了五次:“SMS 数据取证报告已生成![]”。
  • 当我执行“打印(数据)”时。它将所有需要的信息打印到控制台

标签: python pdf reportlab


【解决方案1】:

当前脚本似乎会为 CSV 的每一行覆盖相同的 PDF 文件。下面显示的修改后的脚本会生成表格,如电子表格中所示。我进行了一些重大更改,因此您需要修改文件路径、格式、内容等,以适应您的应用程序。新代码还包括列宽,并删除了一些似乎不必要的字符。

生成的 PDF 示例

用于测试的CSV数据:

['ID','Incoming Number','Date & Time','Read','Sent/Replied','Body','Seen']
(1,'555-555-5555','23-01-2018 17:03:52',1,1,'Where are you at? Are you on your way yet?',1)
(2,'555-555-5555','23-01-2018 17:04:08',1,2,'Yes I am driving at the moment',1)
(3,'555-555-5555','23-01-2018 17:04:34',1,1,'Be here soon or I'm going to call you',1)
(4,'555-555-5555','23-01-2018 17:05:10',1,2,'Yes I will try and pick up the speed and make up time. I'm breaking the speed limit already.',1)
(5,'555-555-5555','23-01-2018 17:05:46',1,1,'Ok',1)

修改后的 Python 脚本

表格样式代码比帮助演示单元格区域如何工作所需的要长。

import csv
import datetime
from reportlab.lib.units import cm, inch
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import *
from reportlab.lib.styles import getSampleStyleSheet

# Data from CSV
with open('smsInfo.csv', "r") as csvfile:
    data = list(csv.reader(csvfile))

elements = []

# PDF Text
# PDF Text - Styles
styles = getSampleStyleSheet()
styleNormal = styles['Normal']

# PDF Text - Content
line1 = 'LYIT MOBILE FORENSICS DIVISION'
line2 = 'Date: {}'.format(datetime.datetime.now().strftime("%d-%m-%y"))
line3 = 'Case Number: 10'
line4 = 'This forensic report on sms card data has been compiled by the forensic'
line5 = 'examiner in conclusion to the investigation into the RTA'
line6 = 'case which occurred on 23/01/2018.'

elements.append(Paragraph(line1, styleNormal))
elements.append(Paragraph(line2, styleNormal))
elements.append(Paragraph(line3, styleNormal))
elements.append(Spacer(inch, .25 * inch))
elements.append(Paragraph(line4, styleNormal))
elements.append(Paragraph(line5, styleNormal))
elements.append(Paragraph(line6, styleNormal))
elements.append(Spacer(inch, .25 * inch))

# PDF Table
# PDF Table - Styles
# [(start_column, start_row), (end_column, end_row)]
all_cells = [(0, 0), (-1, -1)]
header = [(0, 0), (-1, 0)]
column0 = [(0, 0), (0, -1)]
column1 = [(1, 0), (1, -1)]
column2 = [(2, 0), (2, -1)]
column3 = [(3, 0), (3, -1)]
column4 = [(4, 0), (4, -1)]
column5 = [(5, 0), (5, -1)]
column6 = [(6, 0), (6, -1)]
table_style = TableStyle([
    ('VALIGN', all_cells[0], all_cells[1], 'TOP'),
    ('LINEBELOW', header[0], header[1], 1, colors.black),
    ('ALIGN', column0[0], column0[1], 'LEFT'),
    ('ALIGN', column1[0], column1[1], 'LEFT'),
    ('ALIGN', column2[0], column2[1], 'LEFT'),
    ('ALIGN', column3[0], column3[1], 'RIGHT'),
    ('ALIGN', column4[0], column4[1], 'RIGHT'),
    ('ALIGN', column5[0], column5[1], 'LEFT'),
    ('ALIGN', column6[0], column6[1], 'RIGHT'),
])

# PDF Table - Column Widths
colWidths = [
    0.7 * cm,  # Column 0
    3.1 * cm,  # Column 1
    3.7 * cm,  # Column 2
    1.2 * cm,  # Column 3
    2.5 * cm,  # Column 4
    6 * cm,  # Column 5
    1.1 * cm,  # Column 6
]

# PDF Table - Strip '[]() and add word wrap to column 5
for index, row in enumerate(data):
    for col, val in enumerate(row):
        if col != 5 or index == 0:
            data[index][col] = val.strip("'[]()")
        else:
            data[index][col] = Paragraph(val, styles['Normal'])

# Add table to elements
t = Table(data, colWidths=colWidths)
t.setStyle(table_style)
elements.append(t)

# Generate PDF
archivo_pdf = SimpleDocTemplate(
    'SMS Data Report.pdf',
    pagesize=letter,
    rightMargin=40,
    leftMargin=40,
    topMargin=40,
    bottomMargin=28)
archivo_pdf.build(elements)
print('SMS Data Forensic Report Generated!')

【讨论】:

  • 谢谢。我今天会试试这个。
  • 它已经工作了,但我想在整个桌子周围有网格线。我尝试输入“('INNERGRID',(0,0),(-1,-1),1,colors.black)”,但表中的数据似乎超出了网格线。有什么方法可以让网格线根据单元格中的内容移动吗?
  • 我已经想通了。我只是调整了列宽以适应文本的宽度。我的问题现在得到了解答。谢谢你。我现在会接受你的问题。
  • @GreenCoder90 该示例也已使用适当的宽度进行了更正。
  • 谢谢。我现在了解布局了。
猜你喜欢
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 2013-07-16
相关资源
最近更新 更多