Лучший способ создания/заполнения печатных форм и pdf файлов?

У нас есть приложение С#, которое должно печатать сложные формы. Такие вещи, как многостраничные формы соответствия правительствам, которые должны быть в определенном формате. Мы можем получить PDF-копии этих форм и создать поля формы, но не уверены, как заполнить эти данные и создать PDF файл, который можно автоматически распечатать и отправить нашим клиентам (им нужны бумажные копии).

Кроме того, некоторые из форм являются динамическими, так как некоторые страницы должны повторяться (например, для отчета аудита о равных возможностях сотрудника нам может потребоваться включить 5 экземпляров страницы в форму, если она содержит 50 сотрудников, но клиент имеет 250).

В общем, какой лучший способ заполнить и распечатать эти формы? Обратите внимание, что наше приложение основано на С#, но любое решение на любом языке/приложении приветствуется (мы открыты для покупки программного обеспечения или интеграции с другими фреймами, если это необходимо).

Например, что бы использовало использование TurboTax для печати сотен налоговых форм, которые он обрабатывает?

Ответ 1

Здесь есть несколько вариантов.

1) FDF, Формат данных формы. И это ужасный spec-документ, он охватывает только небольшую (редко используемую, сложную) часть формата 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" - это путь к заполняемой форме.

Существует множество продуктов с mail-merge-esque, которые могут перемещаться по FDF и PDF и создавать заполненную форму PDF. Вышеупомянутый iText (и несколько других) могут делать это программно, другие приложения имеют командные строки.

Любая страница, которая может потребоваться повторить, должна быть собственной формой в этой среде. Слияние форм может быть довольно сложным. Есть пара подходов, причем самыми легкими из них являются "сглаживание" полей, поэтому они представляют собой только содержимое страницы (линейное искусство и текст)... тогда вы больше не сливаете PDF-формы.

Конечно, если вы можете контролировать порядок, в котором печатаются вещи, вам совсем не нужно объединять формы. Вы можете просто открыть/распечатать их в правильном порядке.

Насколько я помню, командные команды Acrobat Pro могут импортировать данные FDF и распечатывать. Все, что вам нужно сделать, это генерировать соответствующие файлы FDF, что в основном является тривиальной строкой.

Использование FDF предполагает, что вы уже создали формы PDF, просто ожидая их заполнения. Если это не так...

2) Создавайте ваши формы PDF программно. Я делаю это с iText (базой Java для iTextSharp), хотя на разных языках имеется довольно много библиотек. iText [Sharp] лицензируется под AGPL (или коммерчески). С AGPL любой, у кого есть доступ к вашему OUTPUT, должен иметь доступ к источнику вашего приложения. AGPL является "вирусом" как обычный GPL. Старые версии были доступны в MPL.

Учитывая, что это строго внутреннее и что вы будете печатать PDF файлы, лицензирование не является проблемой.

Было бы значительно более эффективно создавать шаблоны форм, а затем заполнять их... напрямую или через FDF.

Ответ 2

Вы можете попробовать Docotic.Pdf Library. Эта библиотека позволяет заполнять формы в существующих документах, импортировать и экспортировать данные FDF, а также изменять существующие документы и создавать формы с нуля.

Несколько образцов:

Как заполнить существующие формы

Как импортировать FDF в PDF-документ

Как создать текстовые поля

Docotic.Pdf поставляется с коммерческими и бесплатными лицензиями.

Ответ 3

  • Распечатайте форму PDF (в высоком качестве)
  • Сканировать (в высоком качестве)
  • Преобразование отсканированного файла в растровое изображение (*.dib)
  • Использование Visual C (VS 2010, программно)
    • установить свойства страницы (т.е. подготовить страницу, контекст устройства и т.д.).
    • создайте свои шрифты (сколько угодно, конечно)
    • установить начало страницы (вверху страницы)
    • загрузите и используйте StretchDIBits (или подобное) для печати изображения в формате PDF
    • перейти к началу страницы
    • вычислить положение печати (pt.x и pt.y)
    • печать с помощью pDC- > TextOut (или что-то еще, что вы хотите использовать)

Вышеописанное работает с любым количеством полей на любой странице PDF, но требует некоторые рудиментарные знания об основных процессах печати ОС. Это дает вам полный контроль над страницей, и это означает, что вы можете перечеркнуть, распечатать и т.д.... вы можете делать все, что захотите.
Я не вижу никакой проблемы в преобразовании этого в VS 2017 и С#. Никакой библиотеки не нужно - просто старомодное кодирование вручную.

Ответ 4

Если ваша форма основана на технологии AcroForm: просто используйте itext7 для выполнения этой задачи. Добавьте его в свой проект, выполнив следующую команду в консоли диспетчера пакетов NuGet:

Install-Package 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.

Внимание

Имейте в виду, что itext7 распространяется по лицензии AGPL и не является бесплатным для коммерческого использования или закрытого источника. (отдельное спасибо @da_berni за эту необходимую информацию)

Ответ 5

Частичный ответ на ваш вопрос заключается в том, что вам следует изучить библиотеку "ItextSharp", которая является библиотекой с открытым исходным кодом и полезна при создании файлов PDF.

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

Ответ 6

мы используем aspose.words, и я вижу, что у них также есть PDF API.

Ответ 7

Попробуйте с этим:

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