问题
I have a python script that writes text message data from a .csv file to a table in a PDF using reportlab platypus. It only writes the last line of the table into the cell. It ignores all other rows before this point. The only line it writes into the PDF is the last line shown in the excel snip highlighted in yellow. A snippet is also included of what it looks like when it writes it to the PDF as shown.
It also creates the PDF in three or four pages inferring that it is trying to make space for the full table but it won't write it. Here is my code that I have been working with so far. I would like to write it into the PDF document in the same format shown in the Excel snippet. How should I refactor my code to do this?
# 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!')
回答1:
The current script appears to overwrite the same PDF file for each line of the CSV. The modified script shown below generates the table as shown in the spreadsheet. I made some major changes, so you will need to modify the file paths, formatting, content, etc., to fit your application. The new code also includes column widths and removes a few characters that appear to be unnecessary.
Example of the generated PDF
CSV data used to test:
['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)
Modified Python script
The table style code is longer than necessary to help demonstrate how the cell ranges work.
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!')
来源:https://stackoverflow.com/questions/48863462/writing-full-csv-table-to-pdf-in-python