The iTextSharp AcroFields
class has a GetFieldPosition
method.
I am attempting to modify a field's position programmatically. I'm wondering why there is no corresponding SetFieldPosition
, or is there another way of changing a field's size or position?
See this for part of the reason. There isn't actually a singular GetFieldPosition
but instead a plural GetFieldPositions
since you can technically have multiple fields with the same name. So a theoretical SetFieldPositions
would need to take this into account or it might erase some fields.
The other reason is that a field's defining areas aren't always that simple. Take this very simple bit of code:
var tf = new TextField(writer, new iTextSharp.text.Rectangle(100, 400, 500, 500), "name");
writer.AddAnnotation(tf.GetTextField());
It creates a 400x100
text field with corners at 100,400
and 500,500
. It also creates an appearance entry /AP
with a bounding box of 0,0
and 400,100
giving the normal appearance area that you see before clicking into the field. If you literally just changed the "position" by moving the two corners accordingly you'd be okay but since the position is really just a Rectangle
there's nothing stopping you from making it wider or taller. In that case this BBox
entry would need to get updated, too. This is a simple case and iText could probably work through it. Check boxes, however, usually have at least two appearance states that need to be altered. There could also be other cases that it might not make sense to propagate these changes through.
If you want to reposition a field, however, it can still be done, but the burden is on you to do it sanely. Imagine a simple PDF with just this single text field:
var tf = new TextField(writer, new iTextSharp.text.Rectangle(100, 400, 500, 500), "name");
tf.Text = "Hi";
tf.BorderColor = BaseColor.BLACK;
tf.BorderWidth = 1;
writer.AddAnnotation(tf.GetTextField());
You can "move" the text field with a PdfStamper
by getting the actual field and adjusting its RECT
array. The code below.
using (var fs = new FileStream(testFile, FileMode.Create,FileAccess.Write,FileShare.None)) {
using (var reader = new PdfReader(bytes)) {
using (var stamper = new PdfStamper(reader, fs)) {
//Get our name field
var nameField = reader.AcroFields.GetFieldItem("name");
//Grab the first widget inside of it (there could be more)
var w = nameField.GetWidget(0);
//Grab the bounding array
var r = w.GetAsArray(PdfName.RECT);
//Check both of the Y values
r[1] = new PdfNumber(r.GetAsNumber(1).IntValue - 300);
r[3] = new PdfNumber(r.GetAsNumber(3).IntValue - 300);
}
}
}