Search code examples
pythoncsvpdfcanvasreportlab

CSV file data will not write to PDF


enter image description here

I have attempted to write a script below that iterates through a .csv file and writes the containing data to a PDF report using reportlab. So far, the only thing that is writing to the PDF document is the heading information, (heading, date, case number).

It will not write the data below this point which is the table data from the .csv file. I have tried to figure out why is won't write it to the PDF. I have hit a brick wall with this one and I am not sure what I need to do to make the data write to the file. Is there something that I am missing or is there a problem with my code?

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

# import statements
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import portrait
import csv
import datetime
now = datetime.datetime.now()
# PDF document layout
canvas = canvas.Canvas("H:\College Fourth Year\Development Project\Final Year Project 2018\Forensic Reports\SMS Report.pdf", pagesize=letter)

canvas.setLineWidth(.3)
canvas.setFont('Helvetica', 12)
canvas.drawString(30,750,'LYIT MOBILE FORENSICS DIVISION')
canvas.drawString(500,750,"Date: " + now.strftime("%d-%m-%y")) # Prints date of the report(on the fly)
canvas.line(500,747,595,747)
canvas.drawString(500,725,'Case Number:')
canvas.drawString(580,725,"10")
canvas.line(500,723,595,723)

# Introduction text
line1 = 'This forensic report on sms data has been compiled by the forensic'
line2 = 'examiner in conclusion to the investigation into the RTA'
line3 = 'case which occurred on the 23/01/2018.'
textObject = canvas.beginText(30, 700)
lines = [line1, line2, line3]
for line in lines:
    textObject.textLine(line)
canvas.drawText(textObject)

# Writes all data as far as this point. Does not write data to the PDF from here down!!!.

# File that must be written to report
data_file = 'H:\College Fourth Year\Development Project\Final Year Project 2018\ExtractedEvidence\smsInfo.csv'

# Function for importing data
def import_Data(data_file):
    textMessageinfo = csv.reader(open(data_file, "r"))
    for row in textMessageinfo:
        _id = row[0]
        incoming_number = row[1]
        date_and_time = row[2]
        read = row[3]
        sent_replied = row[4]
        body = row[5]
        seen = row[6]
        pdf_filename = _id + incoming_number + date_and_time + read + sent_replied + body + seen + '.pdf'
        generate_report(_id, incoming_number, date_and_time, read, sent_replied, body, seen, pdf_filename)


def generate_report(_id, incoming_number, date_and_time, read, sent_replied, body, seen, pdf_filename):

    smsdata = _id, incoming_number, date_and_time, read, sent_replied, body, seen
    canvas.drawString(50,100, smsdata)
    canvas.showPage()


canvas.save()
import_Data(data_file)

print("Forensic Report Generated!")

Error after running the above code

Traceback (most recent call last):
  File "H:/College Fourth Year/Development Project/Final Year Project 2018/smsParserReportGenerator.py", line 60, in <module>
    import_Data(data_file)
  File "H:/College Fourth Year/Development Project/Final Year Project 2018/smsParserReportGenerator.py", line 49, in import_Data
    generate_report(_id, incoming_number, date_and_time, read, sent_replied, body, seen, pdf_filename)
  File "H:/College Fourth Year/Development Project/Final Year Project 2018/smsParserReportGenerator.py", line 55, in generate_report
    canvas.drawString(50,100, smsdata)
  File "C:\Python34\lib\site-packages\reportlab\pdfgen\canvas.py", line 1542, in drawString
    text = text.decode('utf-8')
AttributeError: 'tuple' object has no attribute 'decode'

Solution

  • you seem to have a cyclic dependency. The generate_report() calls the import_data() function and vise versa but nothing calls either function first ... so the report is never generated.

    The line:

    smsdata = _id, incoming_number, date_and_time, read, sent_replied, body, seen
    

    creates an implicit tupple like this (example csv created based on your template)

    ('1', '2', '2018-02-13 20:26:26', '3', '4', 'body', 'seen')
    

    A tuple does not have a decode() method.

    I guess that you do not want it as a tuple but as a string somehow. Also note that you should save the canvas after the import_Data() function

    e.g. (working code but probably not what you want. It might help you along...

    import csv
    import datetime
    from reportlab.lib.pagesizes import letter
    from reportlab.pdfgen import canvas
    
    now = datetime.datetime.now()
    
    def import_data(pdf, data_file):
        textMessageinfo = csv.reader(open(data_file, "r"))
        for row in textMessageinfo:
            _id = row[0]
            incoming_number = row[1]
            date_and_time = row[2]
            read = row[3]
            sent_replied = row[4]
            body = row[5]
            seen = row[6]
            pdf_filename = _id + incoming_number + date_and_time + read + sent_replied + body + seen + '.pdf'
            generate_report(pdf, _id, incoming_number, date_and_time, read, sent_replied, body, seen, pdf_filename)
    
    
    def generate_report(pdf, _id, incoming_number, date_and_time, read, sent_replied, body, seen, pdf_filename):
        smsdata = "" + _id + incoming_number + date_and_time + read + sent_replied + body + seen
        pdf.drawString(50, 100, smsdata)
        pdf.showPage()
    
    
    def front_page():
        pdf = canvas.Canvas("SMS_Report.pdf", pagesize=letter)
        pdf.setLineWidth(.3)
        pdf.setFont('Helvetica', 12)
        pdf.drawString(30, 750, 'LYIT MOBILE FORENSICS DIVISION')
        pdf.drawString(500, 750, "Date: " + now.strftime("%d-%m-%y"))  # Prints date of the report(on the fly)
        pdf.line(500, 747, 595, 747)
        pdf.drawString(500, 725, 'Case Number:')
        pdf.drawString(580, 725, "10")
        pdf.line(500, 723, 595, 723)
    
        line1 = 'This forensic report on sms data has been compiled by the forensic'
        line2 = 'examiner in conclusion to the investigation into the RTA'
        line3 = 'case which occurred on the 23/01/2018.'
        textObject = pdf.beginText(30, 700)
        lines = [line1, line2, line3]
        for line in lines:
            textObject.textLine(line)
    
        pdf.drawText(textObject)
        return pdf
    
    
    def main():
        data_file = 'smsInfo.csv'
        pdf = front_page()
        import_data(pdf, data_file)
        pdf.save()
        print("Forensic Report Generated!")
    
    
    if __name__ == '__main__':
        main()