2017-01-06 4 views
3

Доброе утро. Я надеюсь, кто-то может мне помочь по этой теме. В прошлом году я создал программу VB.NET, используя iTextSharp, где пользователь мог ввести информацию для заполнения I9, и эта информация заполнила бы PDF-файл и распечатала. С новым I9 я испытываю неопознанные трудности.Auto-Fill I-9 PDF Форма XFA

Во-первых, код не содержит ошибок или что-то еще. Я просто получаю плохой результат, так как вместо заполненной формы я получаю PDF-файл, в котором говорится: «Документ, который вы пытаетесь загрузить, требует Adobe Reader 8 или выше. Возможно, у вас нет установленного Adobe Reader ...» и т. Д. Я убедился, что у меня самая последняя версия Reader, и попытался снова и тот же результат.

Думаю, что, возможно, были изменения в структуре имени поля, я попытался прочитать в формате/полях, как это было в первый раз. (Код ниже). Однако теперь он говорит мне, что нет полей для чтения (AcroFields.Fields.Count = 0).

Private Sub ListFieldNames(pdfTemplate As String) 
    Dim pdfTemplate As String = "c:\Temp\PDF\fw4.pdf" 
    Dim pdfReader As PdfReader = New PdfReader(pdfTemplate) 
    Dim de As KeyValuePair(Of String, iTextSharp.text.pdf.AcroFields.Item) 

    For Each de In pdfReader.AcroFields.Fields 
     Console.WriteLine(de.Key.ToString()) 
    Next 
End Sub 

Итак, я начал выполнять поиск и нашел ссылку на другой тип структуры PDF, на который они могли бы переключиться; РФ. Я, честно говоря, до сих пор не нашел удовлетворительной документации/образцов этого, но я нашел код, который, похоже, должен работать, чтобы читать в структуре XFA PDF. (Код ниже). На самом деле у меня есть два разных метода. Первое, по сути, показывает, что xmlNodes в xfaFields отсутствует. Второй находит узел, называемый «данные» (это единственный, который он находит), но не находит дочерние узлы.

Private Sub ReadXfa(pdfTemplate As String) 
    pdfReader.unethicalreading = True 
    Dim readerPDF As New PdfReader(pdfTemplate) 

    Dim xfaFields = readerPDF.AcroFields.Xfa.DatasetsSom.Name2Node 

    For Each xmlNode In xfaFields 
     Console.WriteLine(xmlNode.Value.Name + ":" + xmlNode.Value.InnerText) 
    Next 
    'Example of how to get a field value 
    ' Dim lastName = xfaFields.First(Function(a) a.Value.Name = "textFieldLastNameGlobal").Value.InnerText 


    Dim reader As New PdfReader(pdfTemplate) 
    Dim xfa As New XfaForm(reader) 
    Dim node As XmlNode = xfa.DatasetsNode() 
    Dim list As XmlNodeList = node.ChildNodes() 
    For i As Integer = 0 To list.Count - 1 
     Console.WriteLine(list.Item(i).LocalName()) 
     If "data".Equals(list.Item(i).LocalName()) Then 
      node = list.Item(i) 
      Exit For 
     End If 
    Next 
    list = node.ChildNodes() 
    For i As Integer = 0 To list.Count - 1 
     Console.WriteLine(list.Item(i).LocalName()) 
    Next 
    reader.Close() 
End Sub 

https://www.uscis.gov/system/files_force/files/form/i-9.pdf?download=1

выше ссылка идет на i9 PDF, предоставленной правительством.

ТАК ... Я думаю, у меня есть несколько вопросов. Самое простое - это если кто-то сделал этот процесс/если они могут мне помочь. Если это не так, если кто-то может указать мне в правильном направлении относительно того, как читать/писать из этого нового файла PDF, это было бы потрясающе. Я, откровенно говоря, даже не знаю, как определить, какой «тип» формы они использовали - AcroField, XFA, что-то еще?

Большое вам спасибо за ваше время/помощь!

ответ

2

Во-первых, извините, я больше не использую vb.net, но вы должны иметь возможность конвертировать следующий код.

Вы уже выяснили, что новая форма - XFA. Существует простой, не программный способ увидеть поля формы и данные. Вы отметили, что обновили версию Adobe Reader, так что, полагаю, вы используете Reader DC. Из опций меню:

Edit => Form Options => Export Data... 

, что экспорт формы в XML файл, вы можете осмотреть. Файл XML дает вам подсказку о том, что для заполнения формы необходим соответствующий XML-документ, который отличается от того, как это делается с AcroForm.

Вот какой простой код, чтобы вы начали.Первый способ, чтобы прочитать пустой документ XML и обновить его:

public string FillXml(Dictionary<string, string> fields) 
{ 
    // XML_INFILE => physical path to XML file exported from I-9 
    XDocument xDoc = XDocument.Load(XML_INFILE); 
    foreach (var kvp in fields) 
    { 
     // handle multiple elements in I-9 form 
     var elements = xDoc.XPathSelectElements(
      string.Format("//{0}", kvp.Key) 
     ); 
     if (elements.Count() > 0) 
     { 
      foreach (var e in elements) { e.Value = kvp.Value; } 
     } 
    } 

    return xDoc.ToString(); 
} 

Теперь, когда у нас есть метод, чтобы создать правильный XML, заполните поля формы с некоторой выборки данных:

var fields = new Dictionary<string, string>() 
{ 
    { "textFieldLastNameGlobal", "Doe" }, 
    { "textFieldFirstNameGlobal", "Jane" } 
}; 
var filledXml = FillXml(fields); 

using (var ms = new MemoryStream()) 
{ 
    // PDF_READER => I-9 PdfReader instance 
    using (PDF_READER) 
    { 
     // I-9 has password security 
     PdfReader.unethicalreading = true; 
     // maintain usage rights on output file 
     using (var stamper = new PdfStamper(PDF_READER, ms, '\0', true)) 
     { 
      XmlDocument doc = new XmlDocument(); 
      doc.LoadXml(filledXml); 
      stamper.AcroFields.Xfa.FillXfaForm(doc.DocumentElement); 
     } 
    } 
    File.WriteAllBytes(OUTFILE, ms.ToArray()); 
} 

Чтобы ответить на ваш последний вопрос, как определить форму «типа», используйте экземпляр PdfReader так:

PDF_READER.AcroFields.Xfa.XfaPresent 

true означает XFA, false средства AcroForm.

+0

Благодарим вас за ввод! Я сейчас попробую попробовать, и я обновлю свои результаты. – Brenda

1

Вот мой последний код на тот случай, если кто-то там сможет его использовать ... У меня есть сообщение об ошибке. Далее на месте, потому что i9 - это смехотворная форма, и я предпочитаю заполнять некоторые вещи несколько иначе, чем они хотят, чтобы я это сделал. Я также рубил, где я устанавливаю некоторые из моих переменных, чтобы сохранить его короче. Еще раз спасибо kuujinbo за вашу помощь!

Private Sub ExportI9() 
    Dim pdfTemplate As String = Path.Combine(Application.StartupPath, "PDFs\2017-I9.pdf") 
    pdfTemplate = Replace(pdfTemplate, "bin\Debug\", "") 


    Dim fields = New Dictionary(Of String, String)() From { 
    {"textFieldLastNameGlobal", Me.tbLast.Text}, 
    {"textFieldFirstNameGlobal", Me.tbFirst.Text}, 
    {"textFieldMiddleInitialGlobal", Mid(Me.tbMiddle.Text, 1, 1)}, 
    {"textFieldOtherNames", Me.tbOtherName.Text}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Top/subEmployeeInfo/subSection1Row2/textFieldAddress", addr1}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Top/subEmployeeInfo/subSection1Row2/textFieldAptNum", ""}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Top/subEmployeeInfo/subSection1Row2/textFieldCityOrTown", city1}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Top/subEmployeeInfo/subSection1Row2/State", state1}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Top/subEmployeeInfo/subSection1Row2/textFieldZipCode", zip1}, 
    {"dateFieldBirthDate", Me.dtpBirth.Value}, 
    {"SSN", Me.tbSSN.Text}, 
    {"fieldEmail", ""}, 
    {"fieldPhoneNum", sphone}, 
    {"radioButtonListCitizenship", citizenship}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subCitizenshipStatus/textFieldResidentType", alienuscis}, 
    {"dateAlienAuthDate", dauth}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subAuthorizedAlien/numFormI94Admission", Me.tbi94.Text}, 
    {"numForeignPassport", Me.tbPassport.Text}, 
    {"CountryofIssuance", Me.tbPassportCountry.Text}, 
    {"numAlienOrUSCIS", usc}, 
    {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subAuthorizedAlien/textFieldResidentType", alienuscis}, 
    {"rbListPerparerOrTranslator", 3}, 
    {"dropdownMultiPreparerOrTranslator", 1}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow2/textFieldFirstName", prepfirst}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow2/textFieldLastName", preplast}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow3/textFieldAddress", Replace(prepadd, "#", "No. ")}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow3/textFieldCityOrTown", prepcity}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow3/State", prepstate}, 
     {"form1/section1Page1/subSection1PositionWrapper/subSection1Bottom/subPreparerTranslator/subPrepererTranslator1/subTranslatorSignature/subRow3/textFieldZipCode", prepzip}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subDocListA1/selectListA1DocumentTitle", doctitle1}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListB/selectListBDocumentTitle", doctitle2}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListC/selectListCDocumentTitle", doctitle3}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subDocListA1/textFieldIssuingAuthority", issued1}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListB/textFieldIssuingAuthority", issued2}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListC/textFieldIssuingAuthority", issued3}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subDocListA1/dateExpiration", expdate1}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListB/dateExpiration", expdate2}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListC/dateExpiration", expdate3}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subDocListA1/textFieldDocumentNumber", docnum1}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListB/textFieldDocumentNumber", docnum2}, 
    {"form1/section2and3Page2/subSection2/subVerificationListsBorder/subListBandCBorder/subDocListC/textFieldDocumentNumber", docnum3}, 
     {"form1/section2and3Page2/subSection2/subCertification/subAttest/dateEmployeesFirstDay", CDate(Me.dtpHired.Value).ToShortDateString}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow2/textFieldLastName", certlast}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow2/textFieldFirstName", certfirst}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow3/textFieldAddress", orgadd}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow3/textFieldCityOrTown", orgcity}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow3/State", orgstate}, 
     {"form1/section2and3Page2/subSection2/subCertification/subEmployerInformation/subEmployerInfoRow3/textFieldZipCode", orgzip}, 
     {"textBusinessOrgName", orgname} 
    } 


    Dim PDFUpdatedFile As String = pdfTemplate 
    PDFUpdatedFile = Replace(PDFUpdatedFile, "I9", Me.tbSSN.Text & "-I9") 
    If System.IO.File.Exists(PDFUpdatedFile) Then System.IO.File.Delete(PDFUpdatedFile) 
    Dim readerPDF As New PdfReader(pdfTemplate) 


    Dim filledXml = FillXml(fields) 
    Using ms = New MemoryStream() 
     Using readerPDF 
      ' I-9 has password security 
      PdfReader.unethicalreading = True 
      Dim stamper As New PdfStamper(readerPDF, ms, ControlChars.NullChar, True) 
      Using stamper 
       Dim doc As New XmlDocument() 
       doc.LoadXml(filledXml) 
       stamper.AcroFields.Xfa.FillXfaForm(doc.DocumentElement) 
      End Using 
     End Using 
     File.WriteAllBytes(PDFUpdatedFile, ms.ToArray()) 
    End Using 
End Sub 


Public Function FillXml(fields As Dictionary(Of String, String)) As String 
    ' XML_INFILE => physical path to XML file exported from I-9 
    Dim xmlfile As String 

    xmlfile = Path.Combine(Application.StartupPath, "PDFs\2017-I9_data.xml") 
    xmlfile = Replace(xmlfile, "bin\Debug\", "") 
    Dim kvp As KeyValuePair(Of String, String) 

    Dim xDoc As XDocument = XDocument.Load(xmlfile) 
    For Each kvp In fields 
     ' handle multiple elements in I-9 form 
     Dim elements = xDoc.XPathSelectElements(String.Format("//{0}", kvp.Key)) 
     If elements.Count() > 0 Then 
      For Each e As XElement In elements 
       On Error Resume Next 
       e.Value = kvp.Value 
      Next 
     End If 
    Next 

    Return xDoc.ToString() 
End Function 
Смежные вопросы