If you’ve ever needed to programmatically add text to a PDF in Ruby, then you know how tricky it can be. PDFs are complex, and finding tools that are both effective and up-to-date can be a challenge. Many guides rely on deprecated tools or outdated information. In this post, I'll walk through a solution I came up with using two tools:
- Prawn: The fast, nimble PDF writer for Ruby
- CombinePDF: The Ruby gem that combines PDFs
My approach looks like this:
- Create a new overlay PDF with the text I want on my existing PDF using Prawn
- Use
CombinePDF
to overlay the new PDF over the existing one so the text appears in the correct spot
This two-step approach is necessary because Prawn
excels at creating new PDFs but does not support modifying existing ones. Meanwhile, CombinePDF
makes it easy to manipulate and merge existing PDFs. By combining these tools, you get the best of both worlds—precision in adding text and flexibility in working with existing documents.
Create a New Overlay PDF Using Prawn
Using Prawn
is pretty straightforward. The Prawn manual has a bunch of helpful tips about what its PDF DSL can do. That is where you want to start to figure out how to arrange text, manipulate pages, and work with shapes.
As an example, getting things going looks like this:
document = Prawn::Document.new
document.text_box "Hello, world", at: [20, 650], width: 200
document.start_new_page
document.text_box "Some other words", at: [30, 500], width: 300
Overlay the New PDF Over the Existing One
To overlay the new PDF, you need to take three steps:
- Create a base PDF to hold your result: This acts as a container for the final combined document.
- Load your existing PDF and add it to the base PDF: This ensures that the original content remains intact and serves as the foundation for the overlay.
- Add your overlay PDF to the base PDF: This step places your new content in the correct position over the existing content, completing the merge.
That all comes together to look like this:
require 'combine_pdf'
require 'prawn'
# Let's create our base PDF to hold our result
output_pdf = CombinePDF.new
# Now let's read the PDF we want to write on and add it to the result
existing_pdf = CombinePDF.load('/path/to/existing.pdf')
existing_pdf.pages.each do |existing_pdf_page|
output_pdf << existing_pdf_page
end
# Let's use Prawn to create our overlay
overlay_document = Prawn::Document.new
overlay_document.text_box "Hello, world", at: [20, 650], width: 200
# Now we'll add the pages of our overlay PDF to our base PDF
overlay_pdf = CombinePDF.parse(overlay_document.render)
overlay_pdf.pages.each_with_index do |overlay_pdf_page, index|
if output_pdf.pages[index]
output_pdf.pages[index] << overlay_pdf_page
else
raise "Overlay PDF has more pages than the existing PDF."
end
end
# Finally, we'll render the result
output_pdf.save('output.pdf')
Top comments (0)