微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PDFBOX acroForm 已填充,但在 Acrobat 阅读器中打开时,值消失

如何解决PDFBOX acroForm 已填充,但在 Acrobat 阅读器中打开时,值消失

我有 PDF 表格,我想用 PDFBox 填写它。它有效,表单已填写,我用其他阅读器或浏览器打开,我可以看到值,但是当我尝试在 Adob​​e Reader 中打开时,值消失了,我尝试了各种可能的方法来找出原因但值不可见。>

我有模板表单,我使用它并填写数据、重命名字段并将其合并到其他文档中,然后重做该过程,直到填写完所有表单。

我不确定这是否与我的代码或 Adob​​e 阅读器有关。

Link to PDF form I need to fill

这是我填充表单的代码


abstract class AbstractPDFFormFiller<T> {

    private val logger = LogManager.getLogger()
    private val merge = PDFMergerUtility()

    private val PAGE_SIZE = 12

    fun fillForm(templatePath: String,data: List<T>,headerParam: Map<String,String>): PDDocument {
        val chunks = getDataChunks(data)
        val totalPages = chunks.size

        if (totalPages == 1) {
            val sourceDocument = getTemplate(templatePath)
            val form = sourceDocument.documentCatalog.acroForm
            fillHeader(form,headerParam,totalPages,data)
            fillData(form,data,totalPages)
            return sourceDocument
        } else {
            val resultDocument = PDDocument()
            chunks.forEachIndexed { currentPage,it ->
                val sourceDocument = getTemplate(templatePath)
                val form = sourceDocument.documentCatalog.acroForm
                fillHeader(form,currentPage,it)
                fillData(form,it,currentPage)
//                mergePDFForm(resultDocument,sourceDocument)
                sourceDocument.save("C:\\Users\\\\Documents\\Downloads\\$currentPage.pdf")
                sourceDocument.close()
            }
            mergeFromdisk(File("C:\\Users\\Documents\\Downloads"),resultDocument)
            return resultDocument
        }
    }

    fun mergeFromdisk(folderPath:File,resultDoc:PDDocument){
        folderPath.listFiles()?.forEach {
            mergePDFForm(resultDoc,PDDocument.load(it))
        }
    }

    private fun mergePDFForm(destination: PDDocument,source: PDDocument) {
        try {
            source.documentCatalog.acroForm.flatten()
            merge.acroFormMergeMode = PDFMergerUtility.AcroFormMergeMode.JOIN_FORM_FIELDS_MODE
            merge.appendDocument(destination,source)
            merge.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly())
        } catch (e: Exception) {
            e.printstacktrace()
        }
    }

    fun getTemplate(templatePath: String): PDDocument {
        val s = javaClass.classLoader?.getResource(templatePath)?.openStream()
        return PDDocument.load(s)
    }

    private fun getDataChunks(data: List<T>): List<List<T>> {
        return data.chunked(PAGE_SIZE)
    }

    fun setValue(
        form: PDAcroForm,fullyQualifiedname: String,value: String,rename: Boolean = false,reNameto: String?
    ) {
        val field = form.getField(fullyQualifiedname)
        field.setValue(value)
        if (rename)
            renameField(
                form = form,fullyQualifiedname = fullyQualifiedname,newName = "${field.fullyQualifiedname}_$reNameto"
            )
    }

    fun renameField(form: PDAcroForm,newName: String) {
        val field = form.getField(fullyQualifiedname)
            ?: throw IllegalArgumentException("Field with $fullyQualifiedname not found")
        if (field.actions != null && field.actions.f != null) field.actions.f = null
        try {
            field.partialName = newName
        } catch (e: Exception) {
            logger.fatal("Cannot rename to PDF form name {} to new name {}",fullyQualifiedname,newName)
        }
    }


    abstract fun fillHeader(
        form: PDAcroForm,map: Map<String,String>,currentPage: Int,totalPage: Int,data: List<T>
    )

    abstract fun fillData(form: PDAcroForm,currentPage: Int)
}


class diversionDataFormFiller : AbstractPDFFormFiller<diversionData>() {
    private val logger = LogManager.getLogger()

    override fun fillHeader(
        form: PDAcroForm,data: List<diversionData>
    ) {
        form.getField("Product Type").setValue(map["Product Type"])
        form.getField("Type of Schedule").setValue(map["Type of Schedule"])
        form.getField("LA Revenue Account Number").setValue(map["LA Revenue Account Number"])
        form.getField("Company Name").setValue(map["Company Name"])
        form.getField("Filling Period").setValue(map["Filling Period"])
        form.getField("Page").setValue((currentPage + 1).toString())
        form.getField("of").setValue(totalPage.toString())
        form.getField("Total").setValue(data.stream().mapTodouble(diversionData::quantity).sum().toString())
        renameField(form,"Product Type","Product Type_$currentPage")
        renameField(form,"Type of Schedule","Type of Schedule_$currentPage")
        renameField(form,"LA Revenue Account Number","LA Revenue Account Number_$currentPage")
        renameField(form,"Company Name","Company Name_$currentPage")
        renameField(form,"Filling Period","Filling Period_$currentPage")
        renameField(form,"Total","Total_$currentPage")
        renameField(form,"Page","Page_$currentPage")
        renameField(form,"of","of_$currentPage")
    }

    override fun fillData(form: PDAcroForm,data: List<diversionData>,currentPage: Int) {
        val fieldTree = form.fieldTree
        data.forEachIndexed { i,element ->
            fieldTree.forEach {
                if (it.fieldType == "Tx") {
                    try {
                        if (it.fullyQualifiedname.startsWith("Date") && it.partialName == i.toString()) {
                            logger.info(
                                "renaming {} to {},{}",it.fullyQualifiedname,"${it.fullyQualifiedname}_$currentPage",it.partialName
                            )
/*                            it.setValue(Util.datetoStr(element.date,"MM/dd/yy"))
                            renameField(form,"${it.partialName}_$currentPage")*/
                            setValue(
                                form,Util.datetoStr(element.date,"MM/dd/yy"),true,"$currentPage"
                            )
                        } else if (it.fullyQualifiedname.startsWith("Name2") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.shipperTaxPayerNumber)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("Name") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.supplierTaxPayerNumber)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("diversion Number") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.importNumber)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("FEIN2") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.shipperTaxPayerNumber)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("FEIN") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.supplierTaxPayerNumber)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("Mode") && it.partialName == i.toString()
                        ) {
                            it.setValue("J")
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("Manifest") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.billOfLading)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("Doc. Number") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.billOfLading)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("Net gallons") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.quantity.toString())
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        } else if (it.fullyQualifiedname.startsWith("New") && it.partialName == i.toString()
                        ) {
                            it.setValue(element.revisedDestination)
                            renameField(form,"${it.fullyQualifiedname}_$currentPage")
                        }
                    } catch (ex: IOException) {
                        ex.printstacktrace()
                    }
                }
            }
        }
    }
}

数据类定义

data class diversionData(
    val terminalirsCode: String,val fuelType: String,val supplierTaxPayerNumber: String,val shipperTaxPayerNumber: String,val quantity: Double,val originalDestination: String,val revisedDestination: String,val importNumber: String?,val date: LocalDate,val billOfLading: String,)

测试填写表格

   @Test
    public void fillFormUsingNewKotlinClass() throws IOException {
        List<diversionData> diversionData = new ArrayList<>();

        for (int i = 0; i < 20; i++) {
            diversionData d = new diversionData(
                "terminal_Code" + i,"Regular" + i,"supplier tax" + i,"shipper tax" + i,1000 + i,"TX","LA","0000" + i,LocalDate.Now().plusDays(i),"123456" + i
            );
            diversionData.add(d);
        }
        //E:/repo/gasjobber-docker/gasjobber-api/src/main/resources/
        String path = "templates/taxFormsPDF/LA/5402(7_06)F.pdf";
        diversionDataFormFiller filler = new diversionDataFormFiller();
        Map<String,String> param = new HashMap<>();
        param.put("Product Type","065");
        param.put("Type of Schedule","22");
        param.put("LA Revenue Account Number","3264660001");
        param.put("Company Name","Test CO.");
        param.put("Filling Period","2020-12");
        PDDocument document =  filler.fillForm(path,diversionData,param);
        document.save(new File("C:\\Users\\Documents\\Downloads\\testpdf.pdf"));
        document.close();
    }

解决方法

页面 /AA/O 条目(“打开页面时应执行的操作”)具有以下内容:

if (!bReset)
{
    this.resetForm();
    bReset = true;
}

所以表单被重置了。

即使手动填写表单并保存、关闭并重新打开,也会发生这种情况。也许这是“formupack”的演示版本,它是故意这样做的。

您可以通过像这样删除页面 /AA 条目来防止这种情况

document.getPage(0).setActions(null);

或者只是删除 /O 条目

document.getPage(0).getActions().setO(null);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?