如何合并/使用iTextSharp的合并与PDF格式可填写表单域? [英] How do I Combine/Merge PDFs with Fillable Form Fields using iTextSharp?

查看:176
本文介绍了如何合并/使用iTextSharp的合并与PDF格式可填写表单域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 iTextSharp的,我怎么可以合并多个PDF文件为一个PDF不失表单域和它们的属性中的每个单独的PDF?

(我会使用流从数据库preFER一个例子,但文件系统是确定的为好)

我发现这code 的作品,但它降低了,我PDF文件,所以我不能使用它。

更新

@马克斯托勒 - 这是code我现在使用基于您的反馈意见(见下文),但它给了我后,保存损坏的文件。我测试了每个code部位分开,这似乎是失败的 MergePdfForms如下功能。我显然不希望使用你的例子的 renameFields 部分原因是我需要的字段名,以保持原样。

 公用Sub MergePdfForms(BYVAL pdfFiles作为ArrayList中,BYVAL outputPath作为字符串)
    暗淡毫秒作为新IO.MemoryStream()
    昏暗的复印机作为新PdfCopyFields(MS)
    对于每个PFILE作为字符串在pdfFiles
        昏暗的阅读器作为新PdfReader(PFILE)
        copier.AddDocument(阅读器)
    下一个
    SaveMemoryStream(MS,outputPath)
    copier.Close()
结束小组

公用Sub SaveMemoryStream(MS为IO.MemoryStream,文件名作为字符串)
    昏暗outStream作为IO.FileStream = IO.File.OpenWrite(文件名)
    ms.WriteTo(outStream)
    outStream.Flush()
    outStream.Close()
结束小组
 

解决方案

字段在PDF中有一个不寻常的特性:具有在相同名称的所有领域同场。它们共享一个值。这是非常方便的时候形式是指同一个人,你有整个形成了一个很好的命名方案。这不是方便当你想放的单一形式20个实例成一个单一的PDF文件。

这使得合并多种形式具有挑战性的,至少可以这样说。最常用的选项(感谢iText的),是扁平化之前,将它们合并形式,此时你没有长合并的形式,问题消失。

另一种选择是,先重命名字段来合并它们。这可以使数据提取困难以后,可以打破脚本,且通常为一PITA。这就是为什么扁平化是这么多受欢迎。

有一类iText的名为 PdfCopyFields ,它会正确地从一个文档复制领域到另一个...这也将合并具有相同名称的字段的正确的,使得他们真正共享一个值和Acrobat / Reader不必须做对文件一堆额外的工作来获得这种方式显示给用户之前。

不过, PdfCopyFields 将不能重命名为您的字段。要做到这一点,你需要得到从 PdfReader 的问题,并呼吁 AcroFields 对象> renameField(字符串,字符串)在每一个领域与 PdfCopyFields 之前。

这一切都是为AcroForm基于PDF表单。如果你正在处理XFA表单(从LiveCycle Designer中的形式),全盘皆输。你必须淤泥与XML,很多。

和天上的帮助你,如果你不得不从两个结合的形式。

所以,屁股-U-ME-荷兰国际集团,你正在使用AcroForm领域,code可能会是这个样子(原谅我的Java):

 公共无效mergeForms(字符串outpath中,字符串inPaths []){
  PdfCopyFields复印机=新PdfCopyFields(新的FileOutputStream(outpath中));
  对于(字符串curInPath:inPaths){
    PdfReader读卡器=新PdfReader(curInPath);
    renameFields(reader.getAcroFields());

    copier.addDocument(读卡器);
  }
  copier.close();
}

私有静态诠释柜台= 0;
私人无效renameFields(AcroFields场){
  设置<字符串> FIELDNAMES = fields.getFields()键设置()。
  字符串prePEND =的String.Format(_%D,计数器++);

  对于(字符串字段名:字段名){
    fields.rename(字段名,prePEND +字段名);
  }
}
 

在理想情况下, renameFields 也将创造一个通用的领域对象命名为prepend's价值,使所有的文件这是孩子们在其他领域。这将使的Acrobat / Reader的生活更方便,避免不必要的显然是保存更改?要求从Acrobat关闭生成的PDF的时候。

是的,这就是为什么Acrobat将有时会问您保存更改时,您什么也没做! Acrobat中做幕后的东西。

Using iTextSharp, how can I merge multiple PDFs into one PDF without losing the Form Fields and their properties in each individual PDF?

(I would prefer an example using streams from a database but file system is ok as well)

I found this code that works but it flattens out my PDFs so I can't use it.

UPDATE

@Mark Storer - This is the code I am using now based on your feedback (see below) but it gives me a corrupt document after the save. I tested each of the code parts separately and it seems to be failing 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

解决方案

Fields in PDFs have an Unusual Property: All fields with the same name are the same field. They share a value. This is handy when the form refers to the same person and you have a nice naming scheme across forms. It's Not Handy when you want to put 20 instances of a single form into a single PDF.

This makes merging multiple forms challenging, to say the least. The most common option (thanks to iText), is to flatten the forms prior to merging them, at which point you're no long merging forms, and the problem Goes Away.

The other option is to rename your fields prior to merging them. This can make data extraction difficult later, can break scripts, and is generally a PITA. That's why flattening is so much more popular.

There's 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, such that they really share a single value and Acrobat/Reader doesn't have to do a bunch of extra work on the file to get it that way before displaying it to a user.

However, PdfCopyFields will not rename fields for you. To do that, you need to get the AcroFields object from the PdfReader in question, and call renameField(String, String) on Each And Every Field prior to merging the documents with PdfCopyFields.

All this is for "AcroForm"-based PDF forms. If you're dealing with XFA forms (forms from LiveCycle Designer), all bets are off. You have to muck with the XML, A Lot.

And heaven help you if you have to combine forms from both.

So ass-u-me-ing that you're working with AcroForm fields, the code might 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 would also create a generic field object named prepend's-value and make all the other fields in the document it's children. This would make Acrobat/Reader's life easier and avoid an apparently unnecessary "save changes?" request when closing the resulting PDF from Acrobat.

Yes, that's why Acrobat will sometimes ask you to save changes when You Didn't Do Anything! Acrobat did something behind the scenes.

这篇关于如何合并/使用iTextSharp的合并与PDF格式可填写表单域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆