I will show two methods to flatten editable form fields in a PDF file. Method 1 is true form flattening and method 2 is just making the editable fields read only. Personally I was using method 1 for some time, however in some instances (more specifically when merging images into a PDF file and messing with the editable fields), this specific method would throw an error upon opening the PDF file in Adobe Reader stating that Acrobat may not display the page correctly, however I never noticed anything wrong with the PDF file, everything was being displayed correctly, but this “error” was kinda annoying, so I opted to change the code a bit to make all the fields Read Only instead of flattening the form.
Below is the code to perform both, flatten the form and make all the fields Read Only.
[topads][/topads]
Method 1
Just create a stamper and set its FormFlattening to true.
C# Code
stamper.FormFlattening = True
VB.Net Code
stamper.FormFlattening = True
Method 2
Create a stamper, read all the AcroFields into an array and loop thru them setting them READ ONLY one by one.
C# Code
string[] fields = stamper.AcroFields.Fields.Select(x => x.Key).ToArray(); for (int key = 0; key <= fields.Count - 1; key++) { stamper.AcroFields.SetFieldProperty(fields(key), "setfflags", PdfFormField.FF_READ_ONLY, null); }
VB.Net Code
Dim fields() As String = stamper.AcroFields.Fields.[Select](Function(x) x.Key).ToArray() For key As Integer = 0 To fields.Count - 1 stamper.AcroFields.SetFieldProperty(fields(key), "setfflags", PdfFormField.FF_READ_ONLY, Nothing) Next
Complete Code
C# Code
private void flattenPdfFile(ref byte[] fileBytes) { PdfReader reader = new PdfReader(fileBytes); MemoryStream ms = new MemoryStream(); PdfStamper stamper = new PdfStamper(reader, ms, "4"); //Creating the PDF in version 1.4 //Method 1 stamper.FormFlattening = true; //Method 1 string[] fields = stamper.AcroFields.Fields.Select(x =>x.Key).ToArray(); for (int key = 0; key <= fields.Count - 1; key++) { stamper.AcroFields.SetFieldProperty(fields(key), "setfflags", PdfFormField.FF_READ_ONLY, null); } stamper.Writer.CloseStream = false; stamper.Close(); ms.Position = 0; fileBytes = ms.ToArray(); ms.Flush(); reader.Close(); }
VB.Net Code
Private Sub flattenPdfFile(ByRef fileBytes As Byte()) Dim reader As PdfReader = New PdfReader(fileBytes) Dim ms As MemoryStream = New MemoryStream() Dim stamper As PdfStamper = New PdfStamper(reader, ms, "4") 'Creating the PDF in version 1.4 'Method 1 stamper.FormFlattening = True 'Method 2 Dim fields() As String = stamper.AcroFields.Fields.[Select](Function(x) x.Key).ToArray() For key As Integer = 0 To fields.Count - 1 stamper.AcroFields.SetFieldProperty(fields(key), "setfflags", PdfFormField.FF_READ_ONLY, Nothing) Next stamper.Writer.CloseStream = False stamper.Close() ms.Position = 0 fileBytes = ms.ToArray() ms.Flush() reader.Close() End Sub'
Consider giving back by getting me a coffee (or a couple) by clicking the following button:
[bottomads][/bottomads]
I’ve made a pdf in Livecycle Designer
When i use your routine, this is nog working (not read only and not showing any data)
Which version of iText are you using?
I’ve had bad experiences with PDF forms created with Livecycle Designer. One of those experiences was when I tried to edit a PDF Form with Acrobat DC, it was telling me that I couldn’t edit it using DC because it was created with Livecycle Designer. My guess is that Livecycle Designer creates forms that are internally different than forms created by Acrobat, so this might be the reason. And I’m using iText 5.2
C#
for (int key = 0; key <= fields.Count – 1; key++) {
stamper.AcroFields.SetFieldProperty(fields(key), "setfflags", PdfFormField.FF_READ_ONLY, null);
}
this is a mix of vb and c# it should read
for (int key = 0; key < fields.length; key++) {
stamper.AcroFields.SetFieldProperty(fields[key], "setfflags", PdfFormField.FF_READ_ONLY, null);
Keep up the good work.
Regards Geoff
Thanks a lot , read only is working now for me with method 1
Any way to only print the field content of a PDF form? I need to programmatically fill out a PDF form then print to a pre-printed form. Sounds weird, but this is my task. My client has pre-printed forms that print in landscape orientation and must get data to print at the correct location. So I thought i’d fill out the form in code then just remove the bottom layer of the form leaving the top layer of the fields. Make sense? can do?