创建/填写印刷表格和pdf的最佳方式?

问题描述 投票:12回答:7

我们有一个C#应用程序,必须打印复杂的表单。多页政府合规表格必须采用特定格式。我们可以获取这些表单的PDF副本并创建表单字段,但不确定如何填写此数据并创建可以自动打印并发送给客户的PDF(他们需要纸质副本)。

此外,某些表单是动态的,因为必须重复某些页面(例如,对于员工平等机会审计报告,如果它拥有50名员工但客户端有250个,我们可能需要在表单中包含5个页面副本)。

一般来说,填充和打印这些表单的最佳方法是什么?请注意,我们的应用程序是基于C#的,但欢迎任何语言/应用程序中的任何解决方案(我们愿意购买软件或在需要时与其他框架集成)。

例如 - TurboTax会用什么来打印出它处理的数百种税表?

c# pdf adobe pdf-generation
7个回答
11
投票

这里有几种选择。

1)FDF,Form Data Format。这是一个糟糕的规范文档,它只涵盖了FDF格式的一小部分(不经常使用的,复杂的)部分。 FDF文件生成相当简单,包含一堆字段/值对(并且可以保存列表选项,以及其他不需要的更高级的东西)和文件关联。打开FDF填写PDF(通过与acrobat / reader的文件关联)。

这是一个示例(使用额外的空格使其更具可读性):

%FDF-1.2
1 0 obj
<< /FDF
  << /Fields  [
    << /V (Communications Co.)/T (Address1)>>
    << /V (29 Communications Road)/T (Address2)>>
    << /V (Busyville)/T (City)>>
    << /V (USA)/T (Country)>>
    << /V (24 January 2000)/T (Date)>>
    << /V (Suzie Smith)/T (Name)>>
    << /V (\(807\) 221-9999)/T (PhoneNumber)>>
    << /V (777-11-8888)/T (SSN)>>
    << /V (NJ)/T (State)>>
  ]
  /F (TestForm.pdf)
  >>
>>
endobj
trailer
<<
  /Root 1 0 R
>>
%%EOF

“/ V”表示字段值,“/ T”是字段的标题。 “/ F”是要填写的表单的路径。

周围有许多邮件合并式产品,可以接收FDF和PDF并生成填写的PDF表单。前面提到的iText(和其他几个)可以通过编程方式执行此操作,其他应用程序具有命令行。

在这种环境中,任何可能需要重复的页面都应该是它自己的形式。合并表单可能非常难。有几种方法,最简单的方法是“扁平化”字段,使它们只是页面内容(艺术线条和文本)......然后你就不再真正合并PDF格式了。

当然,如果您可以控制打印内容的顺序,则根本不需要合并表单。您可以按正确的顺序打开/打印它们。

我记得,Acrobat Pro的批处理命令可以导入FDF数据和打印。您需要做的就是生成相应的FDF文件,这主要是简单的字符串构建。

使用FDF假设您已经制作了PDF表格,等待填写。如果不是这样的话......

2)以编程方式生成PDF表单。我使用iText(iTextSharp的Java基础)来做这件事,尽管有不少语言提供的库。 iText [夏普]是根据AGPL(或商业)许可的。使用AGPL,任何有权访问您的OUTPUT的人都必须能够访问您的应用程序源。 AGPL与常规GPL一样“病态”。 MPL提供旧版本。

鉴于这是严格内部的,您将打印PDF,许可证不是问题。

生成表单模板然后直接或通过FDF填充它们会更有效率。


3
投票

你可以试试Docotic.Pdf Library。该库允许填写现有文档中的表单,导入和导出FDF数据,以及修改现有文档和从头开始创建表单。

几个样本:

How to fill in existing forms

How to import FDF to PDF document

How to create text fields

Docotic.Pdf附带商业和免费许可证。


1
投票

您的问题的部分答案是您应该探索“ItextSharp”库,它是一个开源库,可用于创建PDF文件。

http://sourceforge.net/projects/itextsharp/


1
投票
  1. 打印PDF表格(高质量)
  2. 扫描它(高质量)
  3. 将扫描的文件转换为位图(* .dib)
  4. 使用Visual C(VS 2010,以编程方式) 设置页面属性(即准备页面,设备上下文等...) 创建你的字体(当然,你喜欢多少) 设置页面原点(页面顶部) 加载并使用StretchDIBits(或类似)来打印PDF页面图像 回到页面顶部 计算您的打印位置(pt.x和pt.y) 使用pDC-> TextOut(或您想要使用的任何其他内容)打印

以上内容适用于任何PDF页面上的任意数量的字段,但需要对底层OS打印过程有一些基本知识。它让你完全控制页面,这意味着你可以跨越,打印等....你可以做任何你喜欢的事情。 我认为将其转换为VS 2017和C#没有任何问题。不需要图书馆 - 只需手工制作简单的老式编码。


1
投票

如果您的表单基于AcroForm技术:只需使用itext7即可完成此任务。通过在NuGet包管理器控制台中执行以下命令将其添加到项目中:

安装包itext7

要编写特定的表单字段,请使用与此类似的代码:

PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
var form = PdfAcroForm.GetAcroForm(pdfDoc, true);
var fields = form.GetFormFields();
fields.Get(key).SetValue(value);
form.FlattenFields();
pdfDoc.Close();

在这个片段中,src是PDF文件的来源,dest是生成PDF的路径。 key对应于模板中字段的名称。 value对应于您要填写的值。如果您希望表单保持其交互性,则需要删除form.flattenFields();否则将删除所有表单字段,从而生成平坦的PDF。


0
投票

我们使用aspose.words,我看他们也有一个PDF API


-3
投票

试试这个:

string Filepath = Server.MapPath("/AOF.pdf");
var pdfpath = Path.Combine(Filepath, "");
var Formcontent = ListFieldNames(Filepath);
Formcontent["Name_txt"] =  "T.Test" ;  FillForm(Formcontent); //  var pdfContents = FillForm(pdfpath, Formcontent);

public Dictionary<string, string> ListFieldNames(string Filepath)
{
    //PdfReader pdfReader = new PdfReader(pdfTemplate);
    //StringBuilder sb = new StringBuilder();
    //foreach(DictionaryEntry de in pdfReader.AcroFields.Fields)
    //{
    //    sb.Append(de.Key.ToString() + Environment.NewLine);
    //}
    var Fileds = new Dictionary<string, string>();
    PdfReader pdfReader = new PdfReader(Filepath);
    var reader = new PdfReader(pdfReader);
    foreach (var entry in reader.AcroFields.Fields)
        Fileds.Add(entry.Key.ToString(), string.Empty);
    reader.Close();
    return Fileds;
}

public byte[] FillForm(string pdfPath, Dictionary<string, string> formFieldMap)
{
    var output = new MemoryStream();
    var reader = new PdfReader(pdfPath);
    var stamper = new PdfStamper(reader, output);
    var formFields = stamper.AcroFields;
    foreach (var fieldName in formFieldMap.Keys)
        formFields.SetField(fieldName, formFieldMap[fieldName]);
    stamper.FormFlattening = true;
    stamper.Close();
    reader.Close();
    return output.ToArray();
}

public void FillForm(Dictionary<string, string> Formfiledmap)
{
    string pdfTemplate = Server.MapPath("/AOF.pdf");
    string newFile = @"C:\Users\USer\Desktop\completed_fw4.pdf";
    PdfReader pdfReader = new PdfReader(pdfTemplate);
    PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create));
    AcroFields pdfFormFields = pdfStamper.AcroFields;
    foreach (var fieldName in Formfiledmap.Keys)
        pdfFormFields.SetField(fieldName, Formfiledmap[fieldName]);
    pdfStamper.FormFlattening = true;
    pdfStamper.Close();
}
© www.soinside.com 2019 - 2024. All rights reserved.