title: Issues with filling PDF forms. Should I use C# with IText AcroFields to fill forms programmatically from a database? Or is this solution outdated?
body: <p>TLDR; Having below issues with IText solution, and have not found a "better" option. </p>
  
  <p>Project currently is finding the best way to fill forms programatically from a database. After researching heavily I found a few solutions based on the following criteria and have created a (somewhat working) solution:</p>
  
  <ul>
  <li>We are currently using Access but are moving to SQL in coming months.</li>
  <li>Filling multiple unique forms that are created by state agencies based on user entered. (so we can't just create our own forms.)</li>
  <li>Forms are regularly updated by the agencies, but the data required remains the same, and will be stored in a database.</li>
  </ul>
  
  <p>To solve this I researched things like <a href="https://itextpdf.com/en" rel="nofollow noreferrer">IText</a> which has a ton of tools for PDF manipulation, one small part of that is it can fill a form using AcroField technology. </p>
  
  <p>I also read through a number of resources here including: </p>
  
  <ul>
  <li><a href="https://stackoverflow.com/a/47030621/11210567">This description on using AcroFields and IText to fill forms</a></li>
  <li><a href="https://stackoverflow.com/a/16729981/11210567">This older solution using Docotic</a></li>
  <li><p><a href="https://stackoverflow.com/questions/17876561/fill-a-pdf-form-from-ms-access">This even older solution with Java</a></p>
  
  <p>Among many other resources. I found that IText seemed to be the best supported with some examples and API that helped me create the following:</p>
  
  <p><pre>
  //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 &amp;&amp; !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></pre></li>
  </ul>
  
  <p>This solution does fill forms, but there are some very big issues with it I have not been able to solve: </p>
  
  <ol>
  <li><a href="https://stackoverflow.com/q/55190391/11210567">Changes do not always commit to form (for instance .backgroundcolor)/will show empty until user clicks into form box.</a> </li>
  <li>Value will print but so will form box changes such as .backgroundcolor. </li>
  <li>These forms have redundant fields and AcroForm seems to have issues with parent/child field names from Adobe. (For instance it will rename any like fields)</li>
  <li>There is not an API for C# for Itext7, and I have not been able to solve these problems. </li>
  </ol>
  
  <p>Any help, articles or insight would be appreciated, I know "open ended" questions don't get much help on here but had to try. Thank you. </p>