How to merge / merge PDF files with fields of a fillable form using iTextSharp?

Using iTextSharp , how can I combine several PDF files into one PDF file without losing the form fields and their properties in each individual PDF file?

(I would prefer an example of using streams from a database, but the file system is also good)

I found this code that works, but it smooths my PDF files, so I cannot use it.

UPDATE

@Mark Storer is the code I'm using now, based on your feedback (see below), but it gives me a damaged document after saving. I tested each part of the code separately and does not seem to work in the MergePdfForms function shown below. I obviously don't want to use the renameFields part of your example, because I need the field names to remain "as is".

 Public Sub MergePdfForms(ByVal pdfFiles As ArrayList, ByVal outputPath As String) Dim ms As New IO.MemoryStream() Dim copier As New PdfCopyFields(ms) For Each pfile As String In pdfFiles Dim reader As New PdfReader(pfile) copier.AddDocument(reader) Next SaveMemoryStream(ms, outputPath) copier.Close() End Sub Public Sub SaveMemoryStream(ms As IO.MemoryStream, FileName As String) Dim outStream As IO.FileStream = IO.File.OpenWrite(FileName) ms.WriteTo(outStream) outStream.Flush() outStream.Close() End Sub 
+6
source share
3 answers

Fields in PDF files have an unusual property: all fields with the same name are the same field . They have value. This is useful when a form refers to one person, and you have a good naming scheme for different forms. This is not convenient if you want to put 20 copies of the same form in one PDF file.

This makes merging multiple forms difficult, to say the least. The most common option (thanks to iText) is to smooth the forms before they merge, after which you do not merge the forms for a long time, and the problem goes forward.

Another option is to rename your fields before combining them. This can make it difficult to retrieve data later, it can disrupt scripts and, as a rule, PITA. This is why anti-aliasing is so popular.

There is a class in iText called PdfCopyFields and it will correctly copy fields from one document to another ... it will also merge fields with the same name correctly so that they really share the same value and Acrobat / Reader does not need to do a lot of additional work above the file to get it that way before displaying it to the user.

However, PdfCopyFields will not rename the fields for you. To do this, you need to get the AcroFields object from the AcroFields in question and call renameField(String, String) for each and every field before merging documents with PdfCopyFields .

All this for AcroForm-based PDF forms. If you are dealing with XFA forms (forms from LiveCycle Designer), all bids are disabled. You have to guess with XML, A Lot.

And heaven helps you if you need to combine forms with both.

So, about the fact that you are working with AcroForm fields, the code may look something like this (forgive my Java):

 public void mergeForms(String outpath, String inPaths[]) { PdfCopyFields copier = new PdfCopyFields(new FileOutputStream(outpath) ); for (String curInPath : inPaths) { PdfReader reader = new PdfReader(curInPath); renameFields(reader.getAcroFields()); copier.addDocument(reader); } copier.close(); } private static int counter = 0; private void renameFields(AcroFields fields) { Set<String> fieldNames = fields.getFields().keySet(); String prepend = String.format("_%d.", counter++); for(String fieldName : fieldNames) { fields.rename(fieldName, prepend + fieldName); } } 

Ideally, renameFields will also create a generic field object called prepend's-value and make all other fields in the document child. Would this make Acrobat / Reader's life easier and avoid obviously unnecessary “changes”? a request to close the resulting PDF file from Acrobat.

Yes, that’s why Acrobat sometimes asks you to save changes when you haven’t done anything! The acrobat did something backstage.

+11
source

you can also use this code .... it will merge the entire PDF file without losing the field value.

  Document document = new Document(); try { string destinationfile = desktopPath.Replace(@"d:\outputfile.pdf"); PdfCopyFields copier = new PdfCopyFields(new FileStream(destinationfile, FileMode.Create)); PdfImportedPage page; //Loops for each file that has been listed foreach (string filename in fileList) { flag++; try { //The current file path string filePath = sourcefolder + filename; PdfReader reader = new PdfReader(filePath); copier.AddDocument(reader); } catch { } } copier.Close(); } 
+2
source

Source: https://habr.com/ru/post/890380/


All Articles