Class: FillablePDF
- Inherits:
-
Object
- Object
- FillablePDF
- Includes:
- SuppressWarnings
- Defined in:
- lib/fillable-pdf.rb,
lib/fillable-pdf/field.rb,
lib/fillable-pdf/itext.rb,
lib/fillable-pdf/version.rb,
lib/fillable-pdf/suppress_warnings.rb
Overview
rubocop:disable Metrics/ClassLength
Defined Under Namespace
Modules: ITEXT, SuppressWarnings Classes: Field
Constant Summary collapse
- VERSION =
'0.9.6'
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.
Methods included from SuppressWarnings
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
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/fillable-pdf.rb', line 16 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
36 37 38 |
# File 'lib/fillable-pdf.rb', line 36 def any_fields? num_fields.positive? end |
#close ⇒ Boolean
Closes the PDF document discarding all unsaved changes.
244 245 246 247 |
# File 'lib/fillable-pdf.rb', line 244 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
56 57 58 59 60 |
# File 'lib/fillable-pdf.rb', line 56 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
69 70 71 |
# File 'lib/fillable-pdf.rb', line 69 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
78 79 80 81 82 83 84 85 86 |
# File 'lib/fillable-pdf.rb', line 78 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
195 196 197 198 199 200 |
# File 'lib/fillable-pdf.rb', line 195 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
45 46 47 |
# File 'lib/fillable-pdf.rb', line 45 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
186 187 188 |
# File 'lib/fillable-pdf.rb', line 186 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
177 178 179 |
# File 'lib/fillable-pdf.rb', line 177 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
219 220 221 222 223 |
# File 'lib/fillable-pdf.rb', line 219 def save(flatten: false) tmp_file = "#{Dir.tmpdir}/#{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
231 232 233 234 235 236 237 |
# File 'lib/fillable-pdf.rb', line 231 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
95 96 97 98 99 100 101 |
# File 'lib/fillable-pdf.rb', line 95 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
167 168 169 |
# File 'lib/fillable-pdf.rb', line 167 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
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 140 141 142 |
# File 'lib/fillable-pdf.rb', line 112 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
153 154 155 156 157 158 159 |
# File 'lib/fillable-pdf.rb', line 153 def set_image_base64(key, base64_image_data) tmp_file = "#{Dir.tmpdir}/#{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
207 208 209 210 211 212 |
# File 'lib/fillable-pdf.rb', line 207 def values iterator = @form_fields.keySet.iterator set = [] set << field(iterator.next.toString) while iterator.hasNext set end |