1

I'm trying to remove the character limit from form fields before setting them using iTextSharp. I am able to do this manually using Adobe Acrobat but we are dealing with a large number of PDF documents which we are dynamically stamping the form fields using iTextSharp. We did not build these PDF documents, we are just using them as templates which we are populating with data. I'm wondering if there is a way to remove the character limit of a form field using the api so we don't have to manually check every field for character limits.

I'm guessing this can be done with the SetFieldProperty method but I'm not sure exactly how.

Thanks in advance

Ben
  • 2,058
  • 9
  • 29
  • 39

2 Answers2

3

It's easy if you know the internals of the PDF format! The code below is pretty much the same as the code I wrote for a different type of PDF annotation here. That page will explain things in a little more detail and give you some references. But basically the trick is to loop through each page, then loop through each page's annotations (form fields fall into this category among other things) and then look for text fields that have their maximum length set and just remove that limitation. All of this work is done on a read-only PdfReader object so once we're done we need to loop through again and write it back out using a PdfWriter of some sort.

Below is a full working C# 2010 WinForms app targeting iTextSharp 5.2.1 that shows all of this off. See the comments in the code for further details.

using System;
using System.IO;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            var inputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
            var outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "output.pdf");

            //Setup some variables to be used later
            PdfDictionary PageDictionary = default(PdfDictionary);
            PdfArray Annots = default(PdfArray);

            //Bind a reader to our input PDF
            PdfReader R = new PdfReader(inputFile);
            //Store the number of pages
            int PageCount = R.NumberOfPages;
            //Loop through each page remember that page numbers start at 1
            for (int i = 1; i <= PageCount; i++) {
                //Get the current page
                PageDictionary = R.GetPageN(i);

                //Get all of the annotations for the current page
                Annots = PageDictionary.GetAsArray(PdfName.ANNOTS);

                //Make sure we have something
                if ((Annots == null) || (Annots.Length == 0)) { continue; }

                //Loop through each annotation
                foreach (PdfObject A in Annots.ArrayList) {
                    //Convert the itext-specific object as a generic PDF object
                    PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(A);

                    //See if this annotation has a WIDGET which would be the UI implementation of a form field
                    if (!AnnotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.WIDGET)) { continue; }

                    //See if this annotation is a text field (TX)
                    if (!AnnotationDictionary.Get(PdfName.FT).Equals(PdfName.TX)) { continue; }

                    //See if it has a maximum length specified (MAXLEN)
                    if (AnnotationDictionary.Contains(PdfName.MAXLEN)) {
                        //If so, remove it
                        AnnotationDictionary.Remove(PdfName.MAXLEN);
                    }
                }
            }
            //Next we create a new document add import each page from the reader above
            using (FileStream FS = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
                using (Document Doc = new Document()) {
                    using (PdfCopy writer = new PdfCopy(Doc, FS)) {
                        Doc.Open();
                        for (int i = 1; i <= R.NumberOfPages; i++) {
                            writer.AddPage(writer.GetImportedPage(R, i));
                        }
                        Doc.Close();
                    }
                }
            }
        }
    }
}
Community
  • 1
  • 1
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • Chris, this solution could be helpful but is it possible to alter an existing field (which I know the id/name of) and remove the MAXLEN property before setting the field? Currently I am doing something like: TargetObject.SetField({FieldName}, {text for field}) for each field which needs to be set. TargetObject is an AcroFields object. – Ben Apr 19 '12 at 12:39
0

I was able to figure this out using the information provided by Chris. I was trying to remove any max length restrictions on any field prior to setting the value on it.

            //TargetObject is an AcroFields object
            AcroFields.Item item = TargetObject.GetFieldItem({FieldName});
            if (item != null)
            {
                foreach (var i in item.merged)
                {
                    if (i.GetType() == typeof(PdfDictionary))
                    {
                        PdfDictionary dictionary = (PdfDictionary)i;
                        if (dictionary.Contains(PdfName.MAXLEN))
                        {
                            dictionary.Remove(PdfName.MAXLEN);
                        }
                        break; //no need to continue once we find the dictionary and remove max length
                    }
                }
            }
Ben
  • 2,058
  • 9
  • 29
  • 39
  • hi. Your code doesn't work. There is no merged property, there is a GetMerged(0) and the items in that dictionary are KeyValuePair objects. Do you mind fixing the code. I am trying to do the same but it doesn't seem to have any effect.Thanks! – boggy Nov 18 '16 at 19:39
  • My code is this: `AcroFields.Item item = ctx.Fields.GetFieldItem(ctx.FieldName); if (item != null) { PdfDictionary mergedFieldDictionary = item.GetMerged(0); PdfNumber maxLengthNumber = mergedFieldDictionary.GetAsNumber(PdfName.MAXLEN); if (maxLengthNumber != null) mergedFieldDictionary.Remove(PdfName.MAXLEN); }` but it doesn't have any effect when the pdf is saved via PdfStamp. The constraint is not removed. – boggy Nov 18 '16 at 19:43