Shofiqul Alam Shofiqul Alam - 4 months ago 97
C# Question

Pdf form fields position retrieval with Itext

With iTextSharp, I can retrieve all the form fields that are present in a PDF form.I'm using Adobe acrobat reader to edit the PDF, where I see, every field have a position attribute which denotes where the PDF field will reside in a form.

So my question is, can I read that value ?

For example if I have a form field Name in a PDF form, can I get the position value of this field, like left 0.5 inches, right 2.5 inches, top 2 inches, bottom 2 inches ?

Right now I'm retrieving the form fields with the below code :

string pdfTemplate = @"D:\abc.pdf";
PdfReader reader = new PdfReader(pdfTemplate);

var fields = reader.AcroFields;

int ffRadio = 1 << 15; //Per spec, 16th bit is radio button
int ffPushbutton = 1 << 16; //17th bit is push button
int ff;

//Loop through each field
foreach (var f in fields.Fields)
{
String type = "";
String name = f.Key.ToString();
String value = fields.GetField(f.Key);

//Get the widgets for the field (note, this could return more than 1, this should be checked)
PdfDictionary w = f.Value.GetWidget(0);

//See if it is a button-like object (/Ft == /Btn)
if (!w.Contains(PdfName.FT) || !w.Get(PdfName.FT).Equals(PdfName.BTN))
{
type = "T";
}
else
{
//Get the optional field flags, if they don't exist then just use zero
ff = (w.Contains(PdfName.FF) ? w.GetAsNumber(PdfName.FF).IntValue : 0);

if ((ff & ffRadio) == ffRadio)
{
//Is Radio
type = "R";
}
else if (((ff & ffRadio) != ffRadio) && ((ff & ffPushbutton) != ffPushbutton))
{
//Is Checkbox
type = "C";
}
else
{
//Regular button
type = "B";
}
}

//MessageBox.Show(type + "=>" + name + "=>" + value);
FormFields fld = new FormFields(name, type, value, "inputfield" +form_fields.Count);

form_fields.Add(fld);

if (type.Equals("T"))
addContent(form_fields.Count);
}

Answer

I was about to close this question as a duplicate of Find field absolute position and dimension by acrokey but that's a Java answer, and although most developers have no problem converting the Java to C#, it may be helpful for some developers to get the C# answer.

Fields in a PDF are visualized using widget annotations. One field can correspond with different of those annotations. For instance, you could have a field named name that is visualized on every page. In this case, the value of this field would be shown on every page.

There's a GetFieldPositions() method that returns a list of multiple positions, one for every widget annotations.

This is some code I copied from the answer to the question iTextSharp GetFieldPositions to SetSimpleColumn

IList<AcroFields.FieldPosition> fieldPositions = fields.GetFieldPositions("fieldNameInThePDF");
if (fieldPositions == null || fieldPositions.Count <= 0) throw new ApplicationException("Error locating field");
AcroFields.FieldPosition fieldPosition = fieldPositions[0];
left = fieldPosition.position.Left;
right = fieldPosition.position.Right;
top = fieldPosition.position.Top;
bottom = fieldPosition.position.Bottom;

If one field corresponds with one widget annotation, then left, right, top, and bottom will give you the left, right, top and bottom coordinate of the field. The width of the field can be calculated like this: right - left; the height like this: top - bottom. These values are expressed in user units. By default there are 72 user units in one inch.

If your document contains more than one page, then fieldPosition.page will give you the page number where you'll find the field.

All of this is documented on http://developers.itextpdf.com/