Content Truncation Issue in PDF Generation

I have implemented a PDF generation function in Python using the reportlab library. However, I am encountering an issue where the content is being cut off at the right side of the PDF page. The function is designed to create a chat-like conversation PDF with messages from both users and the assistant.

I have attempted to dynamically adjust the content width based on the available space, but the problem persists. I would appreciate any insights, suggestions, or solutions from the community on how to ensure that the content remains within the PDF and does not get cut off.

Here is the current implementation of the PDF generation function
`from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from io import BytesIO

def generate_pdf(user_identifier, image_base64, conversation_history):
# Create a BytesIO buffer to store the PDF
pdf_buffer = BytesIO()

# Create a PDF document
pdf_canvas = canvas.Canvas(pdf_buffer, pagesize=letter)

# Set font styles
pdf_canvas.setFont("Helvetica", 12)

# Write conversation to PDF
pdf_canvas.drawString(100, 800, f"Chat for User: {user_identifier}")
y_position = 780
max_content_width = letter[0] - 120  # Maximum width available for content

for message in conversation_history:
    role = message['role']
    content = message['content']
    
    label = "User:" if role == 'user' else "Assistant:"
    label_width = pdf_canvas.stringWidth(label, "Helvetica-Bold", 12)

    pdf_canvas.setFont("Helvetica-Bold", 12)
    pdf_canvas.drawString(120, y_position, label)
    pdf_canvas.setFont("Helvetica", 12)

    # Adjust content width dynamically
    content_width = min(pdf_canvas.stringWidth(content, "Helvetica", 12), max_content_width)
    pdf_canvas.drawString(120 + label_width + 10, y_position, content[:content_width])

    y_position -= 20

# Save the PDF to the BytesIO buffer
pdf_canvas.save()

# Get the BytesIO buffer value
pdf_byte = pdf_buffer.getvalue()

return pdf_byte

`

I think it is you who is cutting off the content:

content[:content_width]

Hello @enyatefe,

Here’s an updated version that uses the Paragraph class to wrap text properly within a given width:

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from io import BytesIO

def generate_pdf(user_identifier, conversation_history):
    pdf_buffer = BytesIO()
    
    pdf_doc = SimpleDocTemplate(pdf_buffer, pagesize=letter)
    
    elements = []
    
    styles = getSampleStyleSheet()
    normal_style = styles['Normal']
    
    intro_text = f"Chat for User: {user_identifier}"
    elements.append(Paragraph(intro_text, normal_style))
    elements.append(Spacer(1, 12))  # Add a little space
    
    max_content_width = pdf_doc.width
    
    for message in conversation_history:
        role = message['role']
        content = message['content']
        
        label = "<b>User:</b> " if role == 'user' else "<b>Assistant:</b> "
        message_text = f"{label}{content}"
        
        message_para = Paragraph(message_text, normal_style)
        elements.append(message_para)
        elements.append(Spacer(1, 12))  # Space between messages
    
    pdf_doc.build(elements)
    
    pdf_byte = pdf_buffer.getvalue()
    
    return pdf_byte

Hope this helps!

Kind Regards,
Sahir Maharaj
Data Scientist | AI Engineer

P.S. Lets connect on LinkedIn!

➀ Want me to build your solution? Lets chat about how I can assist!
➀ Join my Medium community of 30k readers! Sharing my knowledge about data science and AI
➀ Website: https://sahirmaharaj.com
➀ Email: sahir@sahirmaharaj.com
➀ 100+ FREE Power BI Themes: Download Now

3 Likes