Class: FillablePDF
- Inherits:
-
Object
- Object
- FillablePDF
- Defined in:
- lib/fillable-pdf.rb,
lib/fillable-pdf/version.rb
Overview
rubocop:disable Metrics/ClassLength
Constant Summary collapse
- VERSION =
'0.9.5.1'
Instance Method Summary collapse
-
#any_fields? ⇒ Boolean
Determines whether the form has any fields.
-
#close ⇒ Boolean
Closes the PDF document discarding all unsaved changes.
-
#field(key) ⇒ Object
Retrieves the value of a field given its unique field name.
-
#field_type(key) ⇒ Object
Retrieves the string type of a field given its unique field name.
-
#fields ⇒ Object
Retrieves a hash of all fields and their values.
-
#initialize(file_path) ⇒ FillablePDF
constructor
Opens a given fillable-pdf PDF file and prepares it for modification.
-
#names ⇒ Object
Returns a list of all field keys used in the document.
-
#num_fields ⇒ Object
Returns the total number of fillable form fields.
-
#remove_field(key) ⇒ Object
Removes a field from the document given its unique field name.
-
#rename_field(old_key, new_key) ⇒ Object
Renames a field given its unique field name and the new field name.
-
#save(flatten: false) ⇒ Object
Overwrites the previously opened PDF document and flattens it if requested.
-
#save_as(file_path, flatten: false) ⇒ Object
Saves the filled out PDF document in a given path and flattens it if requested.
-
#set_field(key, value, generate_appearance: nil) ⇒ Object
Sets the value of a field given its unique field name and value.
-
#set_fields(fields, generate_appearance: nil) ⇒ Object
Sets the values of multiple fields given a set of unique field names and values.
-
#set_image(key, file_path) ⇒ Object
Sets an image within the bounds of the given form field.
-
#set_image_base64(key, base64_image_data) ⇒ Object
Sets an image within the bounds of the given form field.
-
#values ⇒ Object
Returns a list of all field values used in the document.
Constructor Details
#initialize(file_path) ⇒ FillablePDF
Opens a given fillable-pdf PDF file and prepares it for modification.
@param [String|Symbol] file_path the name of the PDF file or file path
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/fillable-pdf.rb', line 13 def initialize(file_path) raise IOError, "File <#{file_path}> is not found" unless File.exist?(file_path) @file_path = file_path begin @byte_stream = ITEXT::ByteArrayOutputStream.new @pdf_reader = ITEXT::PdfReader.new @file_path.to_s @pdf_writer = ITEXT::PdfWriter.new @byte_stream @pdf_doc = ITEXT::PdfDocument.new @pdf_reader, @pdf_writer @pdf_form = ITEXT::PdfAcroForm.getAcroForm(@pdf_doc, true) @form_fields = @pdf_form.getFormFields rescue StandardError => e raise "#{e.} (Input file may be corrupt, incompatible, read-only, write-protected, encrypted, or may not have any form fields)" # rubocop:disable Layout/LineLength end end |
Instance Method Details
#any_fields? ⇒ Boolean
Determines whether the form has any fields.
@return true if form has fields, false otherwise
33 34 35 |
# File 'lib/fillable-pdf.rb', line 33 def any_fields? num_fields.positive? end |
#close ⇒ Boolean
Closes the PDF document discarding all unsaved changes.
241 242 243 244 |
# File 'lib/fillable-pdf.rb', line 241 def close @pdf_doc.close @pdf_doc.isClosed end |
#field(key) ⇒ Object
Retrieves the value of a field given its unique field name.
@param [String|Symbol] key the field name
@return the value of the field
53 54 55 56 57 |
# File 'lib/fillable-pdf.rb', line 53 def field(key) pdf_field(key).getValueAsString rescue NoMethodError raise "unknown key name `#{key}'" end |
#field_type(key) ⇒ Object
Retrieves the string type of a field given its unique field name.
@param [String|Symbol] key the field name
@return the type of the field
66 67 68 |
# File 'lib/fillable-pdf.rb', line 66 def field_type(key) pdf_field(key).getFormType.toString end |
#fields ⇒ Object
Retrieves a hash of all fields and their values.
@return the hash of field keys and values
75 76 77 78 79 80 81 82 83 |
# File 'lib/fillable-pdf.rb', line 75 def fields iterator = @form_fields.keySet.iterator map = {} while iterator.hasNext key = iterator.next.toString map[key.to_sym] = field(key) end map end |
#names ⇒ Object
Returns a list of all field keys used in the document.
@return array of field names
192 193 194 195 196 197 |
# File 'lib/fillable-pdf.rb', line 192 def names iterator = @form_fields.keySet.iterator set = [] set << iterator.next.toString.to_sym while iterator.hasNext set end |
#num_fields ⇒ Object
Returns the total number of fillable form fields.
@return the number of fields
42 43 44 |
# File 'lib/fillable-pdf.rb', line 42 def num_fields @form_fields.size end |
#remove_field(key) ⇒ Object
Removes a field from the document given its unique field name.
@param [String|Symbol] key the field name
183 184 185 |
# File 'lib/fillable-pdf.rb', line 183 def remove_field(key) @pdf_form.removeField(key.to_s) end |
#rename_field(old_key, new_key) ⇒ Object
Renames a field given its unique field name and the new field name.
@param [String|Symbol] old_key the field name
@param [String|Symbol] new_key the field name
174 175 176 |
# File 'lib/fillable-pdf.rb', line 174 def rename_field(old_key, new_key) pdf_field(old_key).setFieldName(new_key.to_s) end |
#save(flatten: false) ⇒ Object
Overwrites the previously opened PDF document and flattens it if requested.
@param [bool] flatten true if PDF should be flattened, false otherwise
216 217 218 219 220 |
# File 'lib/fillable-pdf.rb', line 216 def save(flatten: false) tmp_file = SecureRandom.uuid save_as(tmp_file, flatten: flatten) FileUtils.mv tmp_file, @file_path end |
#save_as(file_path, flatten: false) ⇒ Object
Saves the filled out PDF document in a given path and flattens it if requested.
@param [String] file_path the name of the PDF file or file path
@param [TrueClass|FalseClass] flatten true if PDF should be flattened, false otherwise
228 229 230 231 232 233 234 |
# File 'lib/fillable-pdf.rb', line 228 def save_as(file_path, flatten: false) if @file_path == file_path save(flatten: flatten) else File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close } end end |
#set_field(key, value, generate_appearance: nil) ⇒ Object
Sets the value of a field given its unique field name and value.
@param [String|Symbol] key the field name
@param [String|Symbol] value the field value
@param [NilClass|TrueClass|FalseClass] generate_appearance true to generate appearance, false to let the PDF viewer application generate form field appearance, nil (default) to let iText decide what's appropriate
92 93 94 95 96 97 98 |
# File 'lib/fillable-pdf.rb', line 92 def set_field(key, value, generate_appearance: nil) if generate_appearance.nil? pdf_field(key).setValue(value.to_s) else pdf_field(key).setValue(value.to_s, generate_appearance) end end |
#set_fields(fields, generate_appearance: nil) ⇒ Object
Sets the values of multiple fields given a set of unique field names and values.
@param [Hash] fields the set of field names and values
@param [NilClass|TrueClass|FalseClass] generate_appearance true to generate appearance, false to let the PDF viewer application generate form field appearance, nil (default) to let iText decide what's appropriate
164 165 166 |
# File 'lib/fillable-pdf.rb', line 164 def set_fields(fields, generate_appearance: nil) fields.each { |key, value| set_field key, value, generate_appearance: generate_appearance } end |
#set_image(key, file_path) ⇒ Object
Sets an image within the bounds of the given form field. It doesn’t matter what type of form field it is (signature, image, etc). The image will be scaled to fill the available space while preserving its aspect ratio. All previous content will be removed, which means you cannot have both text and image.
@param [String|Symbol] key the field name
@param [String|Symbol] file_path the name of the image file or image path
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/fillable-pdf.rb', line 109 def set_image(key, file_path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength raise IOError, "File <#{file_path}> is not found" unless File.exist?(file_path) field = pdf_field(key) = field.getWidgets = suppress_warnings { .isEmpty ? field.getPdfObject : .get(0).getPdfObject } orig_rect = .getAsRectangle(ITEXT::PdfName.Rect) border_width = field.getBorderWidth bounding_rectangle = ITEXT::Rectangle.new( orig_rect.getWidth - (border_width * 2), orig_rect.getHeight - (border_width * 2) ) pdf_form_x_object = ITEXT::PdfFormXObject.new(bounding_rectangle) canvas = ITEXT::Canvas.new(pdf_form_x_object, @pdf_doc) image = ITEXT::Image.new(ITEXT::ImageDataFactory.create(file_path.to_s)) .setAutoScale(true) .setHorizontalAlignment(ITEXT::HorizontalAlignment.CENTER) container = ITEXT::Div.new .setMargin(border_width).add(image) .setVerticalAlignment(ITEXT::VerticalAlignment.MIDDLE) .setFillAvailableArea(true) canvas.add(container) canvas.close pdf_dict = ITEXT::PdfDictionary.new .put(ITEXT::PdfName.AP, pdf_dict) pdf_dict.put(ITEXT::PdfName.N, pdf_form_x_object.getPdfObject) .setModified rescue StandardError => e raise "#{e.} (there may be something wrong with your image)" end |
#set_image_base64(key, base64_image_data) ⇒ Object
Sets an image within the bounds of the given form field. It doesn’t matter what type of form field it is (signature, image, etc). The image will be scaled to fill the available space while preserving its aspect ratio. All previous content will be removed, which means you cannot have both text and image.
@param [String|Symbol] key the field name
@param [String|Symbol] base64_image_data base64 encoded data image
150 151 152 153 154 155 156 |
# File 'lib/fillable-pdf.rb', line 150 def set_image_base64(key, base64_image_data) tmp_file = SecureRandom.uuid File.binwrite(tmp_file, Base64.decode64(base64_image_data)) set_image(key, tmp_file) ensure FileUtils.rm tmp_file end |
#values ⇒ Object
Returns a list of all field values used in the document.
@return array of field values
204 205 206 207 208 209 |
# File 'lib/fillable-pdf.rb', line 204 def values iterator = @form_fields.keySet.iterator set = [] set << field(iterator.next.toString) while iterator.hasNext set end |