FillablePDF

Gem Version Build Status

FillablePDF is an extremely simple and lightweight utility that bridges iText and Ruby in order to fill out fillable PDF forms or extract field values from previously filled out PDF forms.

Known Issues

If the gem hangs in development, removing the following gems may fix the issue:

gem 'spring'
gem 'spring-watcher-listen'

If the gem hangs in production, you could try to use puma with a reverse proxy to host the application.

Installation

Ensure that your JAVA_HOME variable is set before installing this gem (see examples below).

  • OSX: /Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home
  • Ubuntu/CentOS: /usr/lib/jvm/java-1.8.0-openjdk

Add this line to your application's Gemfile:

gem 'fillable-pdf'

And then execute:

bundle

Or install it yourself as:

gem install fillable-pdf

If you are using this gem in a script, you need to require it manually:

require 'fillable-pdf'

Usage

First of all, you should open a fillable PDF file:

pdf = FillablePDF.new 'input.pdf'

Always remember to close your document once you're finished working with it in order to avoid memory leaks:

pdf.close

Instance Methods

An instance of FillablePDF has the following methods at its disposal:

  • any_fields? Determines whether the form has any fields.

    pdf.any_fields?
    # output example: true
    
  • num_fields Returns the total number of fillable form fields.

    # output example: 10
    pdf.num_fields
    
  • field Retrieves the value of a field given its unique field name.

    pdf.field(:full_name)
    # output example: 'Richard'
    
  • field_type Retrieves the numeric type of a field given its unique field name.

    pdf.field_type(:football)
    # output example: 4
    
    # list of all field types
    Field::BUTTON
    Field::CHOICE
    Field::SIGNATURE
    Field::TEXT
    
  • fields Retrieves a hash of all fields and their values.

    pdf.fields
    # output example: {first_name: "Richard", last_name: "Rahl"}
    
  • set_field Sets the value of a field given its unique field name and value.

    pdf.set_field(:first_name, 'Richard')
    # result: changes the value of 'first_name' to 'Richard'
    
  • set_fields Sets the values of multiple fields given a set of unique field names and values.

    pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
    # result: changes the values of 'first_name' and 'last_name'
    
  • rename_field Renames a field given its unique field name and the new field name.

    pdf.rename_field(:last_name, :surname)
    # result: renames field name 'last_name' to 'surname'
    # NOTE: this action does not take effect until the document is saved 
    
  • remove_field Removes a field from the document given its unique field name.

    pdf.remove_field(:last_name)
    # result: physically removes field 'last_name' from document
    
  • names Returns a list of all field keys used in the document.

    pdf.names
    # output example: [:first_name, :last_name]
    
  • values Returns a list of all field values used in the document.

    pdf.values
    # output example: ["Rahl", "Richard"]
    
  • save Overwrites the previously opened PDF document and flattens it if requested.

    pdf.save
    # result: document is saved without flatenning
    pdf.save_as(flatten: true)
    # result: document is saved with flatenning
    
  • save_as Saves the filled out PDF document in a given path and flattens it if requested.

    pdf.save_as('output.pdf')
    # result: document is saved in a given path without flatenning
    pdf.save_as('output.pdf', flatten: true)
    # result: document is saved in a given path with flatenning
    

    NOTE: Saving the file automatically closes the input file, so you would need to reinitialize the FillabePDF class before making any more changes or saving another copy.

  • close Closes the PDF document discarding all unsaved changes.

    pdf.close
    # result: document is closed
    

Example

The following example example.rb and the input file input.pdf are located in the test directory. It uses all of the methods that are described above and generates the output files output.pdf and output.flat.pdf.

require 'fillable-pdf'

# opening a fillable PDF
pdf = FillablePDF.new('input.pdf')

# total number of fields
if pdf.any_fields?
  puts "The form has a total of #{pdf.num_fields} fields."
else
  puts 'The form is not fillable.'
end

puts

# setting form fields
pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
pdf.set_fields(football: 'Yes', baseball: 'Yes',
               basketball: 'Yes', nascar: 'Yes', hockey: 'Yes')
pdf.set_field(:date, Time.now.strftime('%B %e, %Y'))

# list of fields
puts "Fields hash: #{pdf.fields}"

puts

# list of field names
puts "Keys: #{pdf.names}"

puts

# list of field values
puts "Values: #{pdf.values}"

puts

# Checking field type
if pdf.field_type(:football) == Field::BUTTON
  puts "Field 'football' is of type BUTTON"
else
  puts "Field 'football' is not of type BUTTON"
end

puts

# Renaming field
pdf.rename_field :last_name, :surname
puts "Renamed field 'last_name' to 'surname'"

puts

# Removing field
pdf.remove_field :nascar
puts "Removed field 'nascar'"
puts

# printing the name of the person used inside the PDF
puts "Signatory: #{pdf.field(:first_name)} #{pdf.field(:last_name)}"

# saving the filled out PDF in another file
pdf.save_as('output.pdf')

# saving another copy of the filled out PDF in another file and making it non-editable
pdf = FillablePDF.new('output.pdf')
pdf.save_as 'output.flat.pdf', flatten: true

# closing the document
pdf.close

The example above produces the following output and also generates the output file output.pdf.

The form has a total of 8 fields.

Fields hash: {:last_name=>"Rahl", :first_name=>"Richard", :football=>"Yes", :baseball=>"Yes", :basketball=>"Yes", :nascar=>"Yes", :hockey=>"Yes", :date=>"August 30, 2019"}

Keys: [:last_name, :first_name, :football, :baseball, :basketball, :nascar, :hockey, :date]

Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "Yes", "Yes", "August 30, 2019"]

Field 'football' is of type BUTTON

Renamed field 'last_name' to 'surname'

Removed field 'nascar'

Signatory: Richard Rahl

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License

The gem is available as open source under the terms of the MIT License.

However, you must also adhere to the iText License when using this gem in your project.