Digital Diplomas

What are AcroForms?


“AcroForm” usually refers to the PDF form that is authored with Adobe Acrobat Pro/Standard and that is not a special type of static or dynamic XFA form authored with Adobe LiveCycle Designer.

AcroForms are PDF files that contain form fields. Data can be entered into these fields (manually or through an automated process) by the end users or the author of the form. Internally AcroForms are annotations or fields applied to a PDF document. AcroForms are easily filled using formatted ASCII or FDF files that contain key:value pairs that define the field names and associated values that are used to populate a form

You can fill out an AcroForm in Acrobat DC mobile products (for iOS and Android) or programmatically using the example illustrated below.


Like to reply
Tomlist

Tomlist#1

Programmatically Replacing the placeholders with values

Open Visual Studio and create a new Console application.

Install itext7 library from Nuget Package Manager.

Import the libraries in your class files to use the itext7 methods in your program.

Code Section

Create a “Helper.cs class” to perform most of the logics to read the pdf, save the pdf, process the pdf and to fill the form fields. This is how the code looks like : -


3 M 31 D 14:04
Tomlist

Tomlist#2

using iText.IO.Util;
using iText.Kernel.Pdf;
using iText.Forms.Fields;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace PdfAcroForm
{
    public class Helper
    {
        private static readonly string savePath;
        private static readonly string saveFileName;

        static Helper()
        {
            savePath = @"C:\Users\akshs\Desktop";
            saveFileName = "AcroFormFieldsFilled.pdf";
        }

        /// <summary>
        /// Entry point for Helper
        /// </summary>
        /// <param name="prop"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool ProcessPDF(dynamic prop, String path)
        {
            try {
                byte[] form = ReadPdf(path);
                using (Stream ms = new MemoryStream(form))
                {
                    var data = (IEnumerable<byte[]>) PdfFormFiller(prop, ms);
                    SavePDF(savePath, saveFileName, data.Single());
                }
                return true;
            }
            catch (Exception ex) {
                return false;
            }
            
        }

        /// <summary>
        /// Read the Pdf
        /// </summary>
        /// <param name="path"></param>
        /// <returns>byte array</returns>
        private byte[] ReadPdf(string path)
        {
            try
            {
                return File.ReadAllBytes(path);
            }
            catch (FileNotFoundException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// To read the image and convert it to base64 string
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string ConvertImageToBase64(string path)
        {
            try {
                Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
                return Convert.ToBase64String(StreamUtil.InputStreamToArray(stream));
            }
            catch (Exception ex) {
                throw ex;
            }
        }

        /// <summary>
        /// This method is used to replace the placeholder values with data
        /// </summary>
        /// <param name="prop"></param>
        /// <param name="form"></param>
        /// <returns>List of byte array</returns>
        private IEnumerable<byte[]> PdfFormFiller(dynamic prop, params Stream[] form)
        {
            return form.Select(pdf => {
                MemoryStream stream = new MemoryStream();

                // Creating a PDF Document
                using (PdfReader reader = new PdfReader(pdf))
                using (PdfWriter writer = new PdfWriter(stream))
                using (PdfDocument document = new PdfDocument(reader, writer))
                {
                    // Reading the AcroForm
                    iText.Forms.PdfAcroForm acroForm = iText.Forms.PdfAcroForm.GetAcroForm(document, false);
                    acroForm.SetGenerateAppearance(true);
                    // Getting the FormFields
                    var fields = acroForm.GetFormFields();
                    foreach (var field in fields)
                    {
                        // Text placeholders are read as PdfTextFormField
                        if (field.Value is PdfTextFormField formField)
                        {
                            string value = Convert.ToString(prop.GetType().GetProperty(field.Key).GetValue(prop, null));
                            formField.SetValue(value);
                        }
                        // Image placeholders as read as PdfButtonFormField
                        else if (field.Value is PdfButtonFormField button)
                        {
                            string path = Convert.ToString(prop.GetType().GetProperty(field.Key).GetValue(prop, null));
                            button.SetImage(path);
                            // if the image is base64 string you can modify the code as in below comment
                            // button.SetValue(ConvertImageToBase64(path));
                            button.SetPushButton(false);
                        }
                    }
                    // flattening the form so the user won't be able to edit
                    acroForm.FlattenFields();
                }
                return stream.ToArray();
            }).ToList();
        }

        /// <summary>
        /// Creating Save Method to save the Filled PDF Form
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filename"></param>
        /// <param name="bytes"></param>
        private void SavePDF(string path, string filename, byte[] bytes)
        {
            try
            {
                string absolutePath = string.Concat(path, "\\", filename);
                File.WriteAllBytes(absolutePath, bytes);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}


3 M 31 D 14:06
Tomlist

Tomlist#3

Also the modified “Program.cs” class now looks like this : -


using System;

namespace PdfAcroForm
{
   class Program
   {
       private static readonly string path;
       private static readonly string Name;
       private static readonly string Contact;
       private static readonly string Email;
       private static readonly string ImagePath;

       /// <summary>
       /// static constructor to fill the static variables
       /// </summary>
       static Program()
       {
           path = @"C:\Users\akshs\Desktop\AcroFormFields.pdf";
           Name = "Aksh Suri";
           Contact = "72XXXXXX03";
           Email = "suriaksh1@gmail.com";
           ImagePath = @"C:\Users\akshs\Desktop\image.png";
       }

       static void Main(string[] args)
       {
           try {
               Helper obj = new Helper();
               bool isCompleted = obj.ProcessPDF(PropertyFiller(), path);
           }
           catch (Exception ex) {
               throw ex;
           }
       }

       /// <summary>
       /// Method to create dynamic properties
       /// </summary>
       /// <returns></returns>
       private static dynamic PropertyFiller()
       {
           return new
           {
               Name = Name,
               Contact = Contact,
               Email = Email,
               Image = ImagePath
           };
       }
   }    
}


3 M 31 D 14:09
Tomlist

Tomlist#4

Please read the comments and description in code to better understand the logics and the methods used.

Note : — Images are read as PDF Buttons Form Fields. You can directly set the path of Image in SetImage method or if you have the base64 Image string then you can set the same using SetValue method. I went through the code in itext7 library and looks like in SetImage Method :

1. Reads the PDF and converts it into byte stream.

2. Convert the byte stream to base64 Image string.

3. Sets the base64 Image string to SetValue method.

So you can skip the first 2 steps and directly use the SetValue if you have base64 Image String (Refer to the comments and “ConvertImageToBase64” method in Helper.cs).


3 M 31 D 14:10