Best way to create/fill-in printed forms and pdfs?
Asked Answered
C

10

22

We have a C# application that must print complex forms. Things like multi-page government compliance forms that must be in a specific format. We can get PDF copies of these forms and create form fields, but aren't sure how to fill in this data and create a PDF that can be auto-printed and sent to our clients (they need paper copies).

Also, some of the forms are dynamic, in that certain pages must be repeated (for example, for an employee equal opportunity audit report we might need to include 5 copies of a page in the form if it holds 50 employees but the client has 250).

In general, what's the best way to populate and print these forms? Note that our application is C#-based, but any solution in any language/app is welcome (we're open to buying software or integrating with other frameworks if needed).

For example - what would something like TurboTax use to print out the hundreds of tax forms that it handles?

Cryogen answered 14/6, 2011 at 5:26 Comment(1)
Our product Gnostice PDFOne .NET can create new PDF forms and also fill existing form fields. PDFOne has a printer component with which you can print PDF documents. We have published a few articles on performing PDF-related tasks in C#. One of them is an article titled Create an Auto-Print PDF but I am not 100% sure if that satisfies your requirement. There is another article titled [PDF Overlay - Stitching PDF Pages Together in .NET](gnostice.com/nIte
T
16

There are several options here.

  1. FDF, Form Data Format. And that's a terrible spec document, it only covers a small (infrequently used, complicated) part of the FDF format. FDF files are fairly trivial to generate, and contain a pile of field/value pairs (and can hold list options, and other fancier stuff you won't need) and a file association. Opening the FDF fills the PDF (via a file association with acrobat/reader).

Here's a sample (with extra whitespace to make it more readable):

%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" indicates a field value, "/T" is a field's title. "/F" is the path to the form to be filled.

There are a number of mail-merge-esque products floating around that can take in an FDF and PDF and produce a filled PDF form. The aforementioned iText (and several others) can do this programmatically, other apps have command lines.

Any page that might need to be repeated should be it's own form in this environment. Merging forms can be Quite Hard. There are a couple approaches, the easiest of them being to "flatten" the fields so they are just page contents (line art & text)... then you're not really merging PDF forms any more.

Of course if you can control the order in which things are printed, you needn't merge the forms at all. You could just open/print them in the correct order.

As I recall, Acrobat Pro's batch commands can import FDF data and print. All you'd need to do would be to generate the appropriate FDF files, which is mostly trivial string building.

Using FDF presumes you have the PDF forms already made, just waiting to be filled out. If that's not the case...

  1. Generate your PDF forms programmatically. I do this with iText (the Java basis of iTextSharp), though there are quite a few libraries available in various languages. iText[Sharp] is licensed under the AGPL (or commercially). With AGPL, anyone with access to your OUTPUT must have access to the source of your application. AGPL is just as "viral" as the regular GPL. Older versions were available under the MPL.

Given that this is strictly internal and that you'll be printing the PDFs, the licensing isn't much of an issue.

It would be considerably more efficient to generate your form templates once then fill them in... either directly or via FDF.

Tendentious answered 14/6, 2011 at 17:25 Comment(2)
I'm pretty sure you have your \T and \V tags flipped. (I tried using your format, it didn't work, I switched it and it did)Manger
\V and \T are keys in a dictionary. The order shouldn't matter, but it wouldn't shock me to find that some 3rd party form parser out there expected a particular order. If that fixed it with Adobe software, I would be shocked.Tendentious
K
7

You can use a recently created Kevsoft.PDFtk package which wraps up PDFtk server.

var pdftk = new PDFtk();

var fieldData = new Dictionary<string, string>()
{
   ["Best Coding Website Box"] = "Stackoverflow",
   ["My Check Box"] = "Yes"
};

var result = await pdftk.FillFormAsync(
   pdfFile: await File.ReadAllBytesAsync("myForm.pdf"),
   fieldData: fieldData,
   flatten: false,
   dropXfa: false
);

if(result.Success)
{
    await File.WriteAllBytes($"{Guid.NewGuid()}.pdf", result.Result);
}

There's more sameples on the GitHub page - https://github.com/kevbite/Kevsoft.PDFtk

Also, there's extra information on this blog post - https://kevsoft.net/2021/05/16/filling-pdf-forms-for-free-with-dotnet-core-and-net-5.html

Kevsoft.PDFtk is licensed under MIT

PDFtk Server is licensed under GPLv2, however, if you're packaging up with an application to be distributed you can buy a redistribution license.

Konya answered 17/5, 2021 at 9:21 Comment(0)
G
4

If your form is based on the AcroForm technology: Just use the itext7 to accomplish this task. Add it to your project by executing following command in your NuGet Package Manager Console:

Install-Package itext7

To write a specific form field, use code similar to this:

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();

In this snippet, src is the source of a PDF file and dest is the path to the resulting PDF. The key corresponds with the name of a field in your template. The value corresponds with the value you want to fill in. If you want the form to keep its interactivity, you need to remove the form.flattenFields(); otherwise all form fields will be removed, resulting in a flat PDF.

Caution

Be aware, that itext7 is licenced under AGPL and isn't free for commercial use or closed source. (special thanks to @da_berni for this necessary information)

Glyptograph answered 11/4, 2019 at 15:1 Comment(1)
One should mention, that itext is licenced under AGPL and isn't free for commercial use or closed source. So it's not "Just use the itext7", just be aware of licencing.Yacov
B
2

You may try Docotic.Pdf Library. This library allows to fill in forms in existing documents, import and export FDF data, as well modify existing documents and create forms from scratch.

Several samples:

How to fill in existing forms

How to import FDF to PDF document

How to create text fields

Docotic.Pdf comes with commercial and free licenses.

Brunhild answered 15/6, 2011 at 12:13 Comment(2)
They certainly don't advertise a free license any more.Helman
bitmiracle.com/pdf-library/free-pdf-library.aspxBrunhild
C
0

we use aspose.words and I see they have a PDF API as well.

Form Field Processing Aspose.PDF for .NET offers the capabilities to add form fields to the PDF document, that is; you can dynamically generate form fields in PDF documents. Just order the position of the form fields as per a table or by custom positioning, and the form fields will be placed in the exact position every time.

Centromere answered 28/6, 2018 at 2:30 Comment(0)
C
0

As of 2020 FreeSpire.PDF looks interesting. Quoting from the site https://www.e-iceblue.com/Introduce/free-pdf-component.html:

Free Spire.PDF for .NET is a Community Edition of the Spire.PDF for .NET, which is a totally free PDF API for commercial and personal use. As a standalone .NET library, Free Spire.PDF for .NET enables developers to create, write, edit, convert, print, handle and read PDF files on any .NET( C#, VB.NET, ASP.NET, .NET Core) applications.

Apparently it's limited to 10 pages maximum.

Cathartic answered 22/7, 2020 at 7:11 Comment(0)
C
-1

Partial answer to your question is that you should explore "ItextSharp" library which is an open source library and is useful in creating PDF files.

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

Coniferous answered 14/6, 2011 at 5:34 Comment(4)
Will this allow us to overlay text onto an existing PDF? We have reporting software to create a PDF from scratch, the problem is that doing so would be a horrendous undertaking (i.e. trying to hand-draw all the government forms).Cryogen
As far as I know it will, there is a book on this library, there you can find various samples for it.Coniferous
itextsharp reached his end of life. It's successor is iText in its 7th version.Jaconet
the successor iText7 is not free for commercial use AFAIKCourtund
M
-1

Because it is missing here: also with pdfSharp it is possible to add values into fields. To see how, take a look at these links: Fill form fields and Create Acroform/add form element

Murdock answered 19/12, 2022 at 17:12 Comment(0)
B
-3
  1. Print the PDF form (in high quality)
  2. Scan it (in high quality)
  3. Convert scanned file into a bitmap (*.dib)
  4. Using Visual C (VS 2010, programmatically)
    • set the page properties (i.e., prepare the page, device context, etc...)
    • create your fonts (as many as you like, of course)
    • set the page origin (top of page)
    • load and use StretchDIBits (or similar) to print the PDF page image
    • go to top of page
    • calculate your print position (pt.x and pt.y)
    • print using pDC->TextOut (or whatever else you want to use)

The above does work with any number of fields on any PDF page but requires some rudimentary knowledge of the underlying OS print processes. It gives you full control of the page and that does mean you can cross out, print over, etc.... you can do whatever you like.
I see no problem whatsoever in converting that to VS 2017 and C#. No library needed - just plain old fashioned coding by hand.

Bolshevik answered 17/1, 2018 at 4:17 Comment(2)
Just... No... Wtf dude... This solution is just pure pain. There are way easier methods for accomplishing this in C#... Why reinventing the wheel by building a cube?Jaconet
dude you just made my day here, one of the best answers I read on stackoverflow.Telex
D
-3

Try with this:

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();
}
Dane answered 9/6, 2018 at 11:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.