保存的文本字段值在使用PDFBOX生成的PDF中无法正确显示 [英] Saved Text Field value is not displayed properly in PDF generated using PDFBOX

查看:1191
本文介绍了保存的文本字段值在使用PDFBOX生成的PDF中无法正确显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import java.io.IOException;

import javax.swing.text.BadLocationException;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.action.PDAnnotationAdditionalActions;
import org.apache.pdfbox.pdmodel.interactive.action.type.PDActionJavaScript;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextbox;
import org.junit.Test;

public class TestPDTextbox {
    @Test
    public void Sample1 () throws IOException, COSVisitorException, BadLocationException {


        PDDocument doc = new PDDocument();
        PDPage page = new PDPage();
        doc.addPage(page);   

        COSDictionary acroFormDict = new COSDictionary(); 
//        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
        acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        doc.getDocumentCatalog().setAcroForm(acroForm);

        COSDictionary cosDict1 = new COSDictionary();
        COSArray rect1 = new COSArray();
        rect1.add(new COSFloat(100));
        rect1.add(new COSFloat(700));
        rect1.add(new COSFloat(200));
        rect1.add(new COSFloat(750));

        cosDict1.setItem(COSName.RECT, rect1);
        cosDict1.setItem(COSName.FT, COSName.getPDFName("Tx")); // Field Type
        cosDict1.setItem(COSName.TYPE, COSName.ANNOT);
        cosDict1.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
        cosDict1.setItem(COSName.T, new COSString("tx1"));
        cosDict1.setItem(COSName.DA, new COSString("/Helv 7 Tf 0 g"));
        cosDict1.setItem(COSName.V, new COSString("Test Value1"));

        PDTextbox textbox = new PDTextbox(doc.getDocumentCatalog().getAcroForm(), cosDict1);

//      textbox.setValue("Test Value");

        page.getAnnotations().add(textbox.getWidget());
        acroForm.getFields().add(textbox);

         doc.save("C:\\PDF\\SampleTextbox.pdf");
         doc.close();
    }
}

问题#1
我创建了一个文本字段,如上面的代码所示,并尝试使用textbox.setValue(Test Value)设置值;方法,但它给出错误,如下所示:

Issue#1 I have created one text field as shown in above code and tried to set value using textbox.setValue("Test Value"); method but it is giving error as shown below :

java.io.IOException: Error: Don't know how to calculate the position for non-simple fonts
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.getTextPosition(PDAppearance.java:1037)
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.insertGeneratedAppearance(PDAppearance.java:558)
    at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.setAppearanceValue(PDAppearance.java:338)
    at org.apache.pdfbox.pdmodel.interactive.form.PDVariableText.setValue(PDVariableText.java:131)
    at sample.pdfbox.example.TestPDTextbox.Sample1(TestPDTextbox.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

问题#2

Issue#2

为了解决问题#1,如果我使用cosDictionary属性设置textBox的值
即cosDict1.setItem(COSName.V,new COSString(Test Value1)) );

In order to fix issue#1, If I set value of textBox using cosDictionary property i.e. cosDict1.setItem(COSName.V, new COSString("Test Value1"));

然后在Adobe Reader中,textBox的值未正确填充。
我必须单击文本框然后才会显示值,一旦我从字段中移出,值再次变为不可见。

Then in Adobe Reader, value of textBox is not populated properly. I have to click on textbox and then only value appears, and once I move out from the field, value again gets invisible.

第3期

Issue#3

为了修复问题#2,我需要将needAppearances标志设置为true,如下所示,然后在PDF中正确显示该字段值。但在此解决方案之后,一旦用户更改字段值,我就无法提取/解析P​​DF字段,我们再次解析此PDF。

In order to fix issue#2, I need to set needAppearances flag to true as shown below, and after that field value is displayed properly in PDF. But after this solution, I`m not able to extract/parse PDF field back once user changes field value and we again parse this PDF.

注意: - Adob​​e Reader中存在此问题,此处打开PDF时,它会提供一些消息,如修复表单字段。一旦我保存PDF并尝试解析acroform字段,就会发现所有字段都被重置或为空。无法提取字段名称或字段值。

Note:- This issue exists in Adobe Reader, here while opening PDF it gives some message too like fixing form fields up. And once I save PDF and tried to parse acroform fields, all fields are found to be reset or null. None of the field name or field values can be extracted.

因此使用acroFormDict.setBoolean(COSName.getPDFName(NeedAppearances),true);在代码中似乎有风险,它会在PDF解析中产生其他问题,因此无法使用。

So using acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true); in code seems risky and it creates other issue in PDF parsing so it cannot be used.

COSDictionary acroFormDict = new COSDictionary(); 
        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
        acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        doc.getDocumentCatalog().setAcroForm(acroForm);

我想,我需要为文本字段设置PDAppearanceDictionary,但我不知道这样做和是否需要为每个字段或acroform级别设置。

I think, I need to set PDAppearanceDictionary for text fields but I don`t know to do that and whether I need to set for each field or at acroform level.

请帮助我解决此问题我应该如何解决。
我正在使用PDFBOX版本1.8.10。

Please help me with this issue how should I resolve. I`m using PDFBOX version 1.8.10.

推荐答案

在上面的问题中,我通过添加修复了问题#1用于acroform的页面资源,并为文本使用了正确的Default Appearance字符串。现在我不需要将needsAppearance标志设置为true。

In above question, I fixed Issue#1 by adding page resources to acroform and used proper Default Appearance string for text. Now I don`t event require to set needsAppearance flag to true.

        PDFont font = PDType1Font.HELVETICA;
        PDResources res = new PDResources();
        String fontName = res.addFont(font);
        String defaultAppearance = "/"+fontName+" 7 Tf 0 g";

        COSDictionary acroFormDict = new COSDictionary(); 
        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), false);
        acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());
        acroFormDict.setItem(COSName.DA, new COSString(defaultAppearance));

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        acroForm.setDefaultResources(res);

检查下面的整个更正代码:

Check entire corrected code below:

import java.io.IOException;

import javax.swing.text.BadLocationException;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextbox;
import org.junit.Test;

public class TestPDTextbox {
    @Test
    public void Sample1 () throws IOException, COSVisitorException, BadLocationException {


        PDDocument doc = new PDDocument();
        PDPage page = new PDPage();
        doc.addPage(page);   

        PDFont font = PDType1Font.HELVETICA;
        PDResources res = new PDResources();
        String fontName = res.addFont(font);
        String defaultAppearance = "/"+fontName+" 7 Tf 0 g";

        COSDictionary acroFormDict = new COSDictionary(); 
        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), false);
        acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());
        acroFormDict.setItem(COSName.DA, new COSString(defaultAppearance));

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        acroForm.setDefaultResources(res);

        doc.getDocumentCatalog().setAcroForm(acroForm);

        COSDictionary cosDict1 = new COSDictionary();
        COSArray rect1 = new COSArray();
        rect1.add(new COSFloat(100));
        rect1.add(new COSFloat(700));
        rect1.add(new COSFloat(200));
        rect1.add(new COSFloat(750));

        cosDict1.setItem(COSName.RECT, rect1);
        cosDict1.setItem(COSName.FT, COSName.getPDFName("Tx")); // Field Type
        cosDict1.setItem(COSName.TYPE, COSName.ANNOT);
        cosDict1.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
        cosDict1.setItem(COSName.T, new COSString("tx1"));
        cosDict1.setItem(COSName.DA, new COSString(defaultAppearance));
//        cosDict1.setItem(COSName.V, new COSString("Test Value1"));

        PDTextbox textbox = new PDTextbox(doc.getDocumentCatalog().getAcroForm(), cosDict1);

      textbox.setValue("Test Value");

        page.getAnnotations().add(textbox.getWidget());
        acroForm.getFields().add(textbox);

         doc.save("C:\\PDF\\SampleTextbox.pdf");
         doc.close();
    }
}

这篇关于保存的文本字段值在使用PDFBOX生成的PDF中无法正确显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆