Проблемы с заполнением PDF форм.Должен ли я использовать C # с IText AcroFields для программного заполнения форм из базы данных?Или это решение устарело? - PullRequest
0 голосов
/ 20 марта 2019

TLDR;Имея ниже проблемы с решением IText, и не нашли «лучший» вариант.

В настоящее время проект находит лучший способ программного заполнения форм из базы данных.После тщательного исследования я нашел несколько решений на основе следующих критериев и создал (несколько работающее) решение:

  • В настоящее время мы используем Access, но в ближайшие месяцы переходим на SQL.
  • Заполнение нескольких уникальных форм, которые создаются государственными органами на основе введенного пользователем.(поэтому мы не можем просто создавать наши собственные формы.)
  • Формы регулярно обновляются агентствами, но необходимые данные остаются неизменными и будут храниться в базе данных.

Чтобы решить эту проблему, я исследовал такие вещи, как IText , который имеет массу инструментов для работы с PDF, одна небольшая часть которого заключается в том, что он может заполнять форму с использованием технологии AcroField.

Я также прочитал ряд ресурсов, в том числе:

  • Это описание использования AcroFields и IText для заполнения форм
  • Это старое решение с использованием Docotic
  • Это еще более старое решение с Java

    Среди многих других ресурсов.Я обнаружил, что IText лучше всего поддерживается с некоторыми примерами и API, которые помогли мне создать следующее:

    //Creates form
    public virtual void ManipulatePdf(string src, string dst, DataGridViewRow dataRow)
    {
        //Initialize PDF document
        PdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(dst));
        PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
        //form.RemoveXfaForm();
        //form.SetNeedAppearances(true);
        IDictionary fields = form.GetFormFields();
        PdfFormField toSet;
        //visits each field, fills dependant on whether dgv column exists
        foreach (string field in fields.Keys)
        {
            switch (dataGridView1.Columns.Contains(field))
            {
                case false:
                    switch (field)
                    {
                        case "Date":
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue(dateTime.ToString("MM/dd/yy"));
                            break;
                        case "Period_YY":
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue(dateTime.ToString("yy"));
                            break;
                        case "Period_YY2":
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue(dateTime.ToString("yy"));
                            break;
                        case "Period_Month_Start":
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue(dateTime.AddMonths(-1).ToString("MMMM"));
                            break;
                        case "Client_Name2":
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue(dataRow.Cells["Client_Name"].Value.ToString());
                            break;
                        default:
                            fields.TryGetValue(field, out toSet);
                            toSet.SetValue("0");
                            //this setting does not commit, issue with hybrid XFA/AcroForm
                            //.SetBackgroundColor(ColorConstants.YELLOW);
                            break;
                    }
                    break;</p>
    
    <code>        case true:
                if (dataRow.Cells[field].Value != null && !DBNull.Value.Equals(dataRow.Cells[field].Value))
                {
                    string value = dataRow.Cells[field].Value.ToString();
                    fields.TryGetValue(field, out toSet);
                    //this value is sometimes not visable on finished form
                    toSet.SetValue(value);
                }
                break;
    
            default:
                break;
        }
    }
    //form.RemoveXfaForm();
    //pdf.GetCatalog().Remove(PdfName.Perms);
    //form.FlattenFields();
    pdf.Close();
    }
    </code>

Это решение заполняет формы, но есть некоторыеочень большие проблемы, которые я не смог решить:

  1. Изменения не всегда фиксируются в форме (например, .backgroundcolor) / будут отображаться пустыми, пока пользователь не нажмет на поле формы.
  2. Значение будет напечатано, но при этом будут сформированы такие изменения, как .backgroundcolor.
  3. Эти формы имеют избыточные поля, и в AcroForm, похоже, есть проблемы с именами родительских / дочерних полей от Adobe.(Например, он будет переименовывать любые подобные поля)
  4. Не существует API для C # для Itext7, и я не смог решить эти проблемы.

Буду признателен за любую помощь, статьи или понимание, я знаю, что «открытые» вопросы здесь не сильно помогают, но нужно было попробовать.Спасибо.

...