Add text to existing pdf using ruby - ruby-on-rails

I have an rails application that is joining any count of pdf files. Now I need to add a numbering to the joined pdf using ruby.
Is there a state of the art way to add text or other content to an existing pdf file using ruby?

Working with PDF's is really challenging in Ruby/Rails (so I have found out!)
This is the way I was able to add text dynamically to a PDF in rails.
add this gem to your gem file gem "combine_pdf"
and then you can use code like this:
# get the record from the database to add dynamically to the pdf
user = User.last
# get the existing pdf
pdf = CombinePDF.load "#{Rails.root}/public/pdf/existing_pdf.pdf"
# create a textbox and add it to the existing pdf on page 2
pdf.pages[1].textbox "#{user.first_name} #{user.last_name}", height: 20, width: 70, y: 596, x: 72
# output the new pdf which now contains your dynamic data
pdf.save "#{Rails.root}/public/pdf/output#{Time.now.to_s}.pdf"
You can find details of the textbox method here:
https://www.rubydoc.info/gems/combine_pdf/0.2.5/CombinePDF/Page_Methods#textbox-instance_method
I spent days on this working through a number of different gems:
prawn
wicked_pdf
pdfkit
fillable_pdf
But this was by far the most smooth solution for me as of 2019.
I hope this saves someone a lot of time so they don't have to go through all the trial and error I had to with PDF's!!

This solution worked well for me...
Prawn::Document.generate("output.pdf", :template => "/path/to/template.pdf") do
text "This is a text in a copied pdf.", :align => :center
end

You can use CombinePDF for that.
I wrote it because Prawn dropped their template support and I needed a native replacement.
Your code might look something like this:
pdf = CombinePDF.new
pdf << CombinePDF.new("file1.pdf")
pdf << CombinePDF.new("file2.pdf")
pdf.number_pages
pdf.save "output.pdf"
look at the documentation for the different formatting options - I love to surround the numbering with a rounded box (it's in the features, should be easy to play with).

Related

How to get rid of weird box characters in PDFs generated with Prawn?

I am running a Rails 6 app where users can convert their contents into PDFs.
I am using Prawn to generate the PDFs.
Most PDFs look fine but some of them contain empty (?) box characters. I simply don't understand where they come from and I have no way of asking our users. This is a screenshot of one of those PDF files:
How can I get rid of those box characters?
My guess is that our users are copying contents from their word processors (e.g. MS Word) and that these contents contain hidden formatting, tabs, etc.
How can I get rid of those?
OK, fixing this issue was pretty simple. I just hadn't realise that tabs were causing the trouble and that Prawn has no way of handling them (apparently).
So to make Prawn happy I just did this in my model:
class Project < ApplicationRecord
before_save :replace_tabs
def replace_tabs
number_of_spaces = 4
description.gsub!("\t", ' ' * number_of_spaces)
end
end

Fill PDF form with data and images

My goal is to fill the existing PDF interactive form with user data.
Requirements for this are:
it should be able to insert data into text fields;
it should be able to insert an image on the XY position.
I found FillablePDF gem for inserting data into interactive PDF forms. But, can't find if I could insert an image.
For inserting an image I found Prawn gem.
Is there better way or solution for this with only FillablePDF gem?
You can do both tasks with the latest version of HexaPDF which has gained support for AcroForm interactive forms. HexaPDF is a pure Ruby PDF manipulation and creation library, so you wouldn't need to rely on iText and Java like with FillablePDF.
The code for your task would be something like this:
require 'hexapdf'
doc = HexaPDF::Document.open(input_pdf_file)
doc.acro_form.field_by_name('Name of text field').field_value = 'New value'
doc.pages[0].canvas(type: :overlay).image(image_file, at: [x, y])
doc.write('output.pdf')
Note that if this is for a commercial project you will most likely need the commercial license of HexaPDF.
Alternatively, using Prawn with the prawn-blank gem should also work.
(Nota bene: I'm the author of HexaPDF.)

Excel to pdf conversion in rails4 with libreoffice

In a rails 4 application, how can I convert an excel spreadsheet file into pdf.
When I am trying to implement Excel to pdf the contents are listed in different pages if excel column size is large.
How to generate the pdf without moving data to next pages in pdf.
Please help,
Thanks
So you basically have two options you can either implement this yourself and use a CSV gem/library (default CSV, faster CSV, or smarter CSV) assuming that by "excel" a CSV is acceptable. If a CSV is not acceptible you can use the axlsx gem instead. Then for pdf conversion you can use something like prawn. If you decide to build this yourself follow these steps.
Create a controller that will handle Reports, I suggest using the rails g controller report upload generate_table show generate_pdf generator to create a controller and a view for the upload process
Create a file upload form in the upload view.
On submit you will send the file to the generate action processing with one of the CSV or excel gems
Once processed your end product should be an array or hash (as an instance variable) and you can send that to the show action
In the show view you will iterate of that hash/array and incapsulate the contents in a html table.
On the show view you should have a button that will send that same hash/array to the generate_pdf controller action where you will use prawn to create a pdf, you can use something like send_data to the send the completed pdf file back to the user.
This is roughly how you could go about it less the low level details. Now if you wanted to use an out of the box solution you could use something like Ruport. Ruport will handle most of the heavy lifting for you the only thing is you need to have your models and associations set up to use it the way it is designed, and that may not be an option for you.

PrawnPDF Flip Entire PDF

I'm using Prawn PDF to create a label that I send to a label printer, but the label prints upside down. This is important as the shipping labels we use come with some print already on it. The setup I'm using (an iPad through a Lantronix xPrintServer to a Zebra Printer) won't allow me to flip it using the drivers.
So I'm wanting to know if there is a way using Prawn (or even just Rails) to flip the entire document (which contains 2+ pages) so it prints out correctly on the labels. The order of the pages isn't essential.
I haven't used Prawn lately, but I'm pretty sure using the rotate method at the top of your code will work. You'll just need to either set the origin to the center of the page, or use translate to reposition the content after rotation. Page 29 in the manual (PDF) has some example code.
You could save the pdf to a file and then use the awesome pdftk to rotate the saved pdf, then send the amended version.
https://www.pdflabs.com/docs/pdftk-cli-examples/
EDIT - pdftk is not a library/plugin/gem, or any kind of Ruby for that matter. It's a command line tool which you would use like this, in your controller, replacing your current "generate and send pdf" code.
#instead of sending the pdf straight to the user, save it to a file
#i'm not sure how to do this in prawn but it can't be difficult
#rotate the original to a new file
`pdftk /path/to/original.pdf cat 1-endsouth output /path/to/rotated.pdf`
#you could test whether the rotated file exists here as an error-check
#then use send_file to send the rotated one as the response.
send_file "/path/to/rotated.pdf", :type => "application/pdf"

Carrierwave: how to get a version of a pdf that only has certain pages?

In my rails App, I'm using carrierwave. I have a PdfUploader, and in there, I want there to be a version of the pdf with say only the first 3 pages. There's a lot out there on how to get the first page or a particular page as an image, or how to get each page as a separate image, but I want a version of the pdf that has say the first 3 pages together (with the rest of the pdf split off).
Just like how you could make it so this gives you a "thumb" version of the pdf
pdf.thumb.url
Something like this would be nice
pdf.pages([1, 2, 3]).url
Would the answer have something to do with using "manipulate!"?
I've found a way to do it, I think. At the very least, it's a strong step in the right direction. Plop this in pdf_uploader.rb:
version :seq_of_imgs do
process make_seq_of_imgs: [ [1, 2, 3] ]
end
def make_seq_of_imgs(page_arr=[])
manipulate! do |page, index|
if page_arr.include?(index+1)
page
end
end
end
With that, pdf.seq_of_images.url will give you the first 3 pages of the pdf. Albiet, the quality has been messed with a bit. I'll be looking into this.
Update: I think the Grim gem is also a great help in dealing with pdf pages

Resources