使用 iText 将用户输入添加到 PDF 表单

Using iText to add user input to PDF form

嘿,所以我正在尝试使用 iText 来获取用户添加的字符串,然后将它们添加到我导入到应用程序中的可填写 PDF 中。但是,我的应用无法识别我添加的预先描述的字符串。我只会添加一些代码片段,这样任何人都可以告诉我哪里出了问题。对不起,如果这听起来像是一个薄弱的问题,但这是我第一次使用 iText。

这是我的MainActivity.java

public class Main extends Activity {
EditText editText,editText2,editText3,editText4,editText5,editText6,editText7,editText8,editText9,editText10;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
    final Customer newCustomer=new Customer();
    try {
        reader=new PdfReader(getResources().openRawResource(R.raw.pgform));
    } catch (IOException e) {
        e.printStackTrace();
    }



    findViewsById();

    savebutton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Customer newCustomer=new Customer();
            //newCustomer.one(editText.getText().toString());
            //newCustomer.two(editText2.getText().toString());
            OutputStream output=null;
            try {
                reader=new PdfReader(getResources().openRawResource(R.raw.pvgform));
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                PdfStamper stamper=new PdfStamper(reader,output);
                AcroFields acroFields=stamper.getAcroFields();
                acroFields.setField("fullnameorinitials",one);
                acroFields.setField("agedob",two);
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    });



}
private void findViewsById(){ 
    editText=(EditText)findViewById(R.id.editText);
    editText2=(EditText)findViewById(R.id.editText2);
    editText3=(EditText)findViewById(R.id.editText3);
    editText4=(EditText)findViewById(R.id.editText4);
    editText5=(EditText)findViewById(R.id.editText5);
    editText6=(EditText)findViewById(R.id.editText6);
    editText7=(EditText)findViewById(R.id.editText7);
    editText8=(EditText)findViewById(R.id.editText8);
    editText9=(EditText)findViewById(R.id.editText9);
    editText10=(EditText)findViewById(R.id.editText10);
}


public class Customer{
    String one=editText.getText().toString();
    String two=editText2.getText().toString();
    String three=editText3.getText().toString();
    String four=editText4.getText().toString();
    String five=editText5.getText().toString();
    String six=editText6.getText().toString();
    String seven=editText7.getText().toString();
    String eight=editText8.getText().toString();
    String nine=editText9.getText().toString();
    String ten=editText10.getText().toString();

}


}

似乎有问题的代码行是当我尝试使用我的应用程序中的每个 editText 设置 PDF 中的字段时。

acroFields.setField("fullnameorinitials",one);

错误在字符串值(一)上。 请提供任何形式的生殖帮助!

代码中有两个问题,一个是关于变量范围阻止编译,另一个是关于 iText API 使用阻止正确结果 PDF。

变量作用域

变量必须声明并在使用它们的范围内可见。 onetwo 在匿名内部 class 中的 onClick 实现不是这种情况,基于 Main.onCreate 中构造的 View.OnClickListener

@Override
protected void onCreate(Bundle savedInstanceState)
{
    [...]
    savebutton.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            [...]
            try
            {
                PdfStamper stamper=new PdfStamper(reader,output);
                AcroFields acroFields=stamper.getAcroFields();
                acroFields.setField("fullnameorinitials",one);
                acroFields.setField("agedob",two);
            }
            [...]
        }
    });
}

这段代码可以使用所有静态Main变量,手头Main实例的所有非静态成员变量,实例化前在onCreate中声明的所有final变量OnClickListener,匿名class的所有静态变量和手头实例的所有非静态变量,以及使用one和[=之前onClick中的所有变量15=].

唯一的变量onetwo声明在另一个内部class,Customer.

假设 Customer class 成员的初始化值是 onClick 中所需的数据,编译失败可以这样修复:

            [...]
            try
            {
                PdfStamper stamper=new PdfStamper(reader,output);
                AcroFields acroFields=stamper.getAcroFields();
                acroFields.setField("fullnameorinitials", editText.getText().toString());
                acroFields.setField("agedob", editText2.getText().toString());
            }
            [...]

(您当然可以插入一个 Customer bean 来分离关注点,但在那种情况下请使用独立于视图字段的合理的成员名称,例如 fullName而不是 one.)

现在可以编译代码了,但仍然不一定会产生正确的结果。因此:

iText API 使用

在上面的代码中,实例化了 PdfStamper,然后用它设置了一些字段,然后什么都没有...另一方面,iText API 合同期望 PdfStamper 使用后要关闭的实例:在 close 期间,PDF 输出完成。

因此:

            [...]
            try
            {
                PdfStamper stamper=new PdfStamper(reader,output);
                AcroFields acroFields=stamper.getAcroFields();
                acroFields.setField("fullnameorinitials", editText.getText().toString());
                acroFields.setField("agedob", editText2.getText().toString());
                stamper.close();
            }
            [...]

此外,iText PdfStamper 需要写入某个目标,在原始代码中,目标是从使用的 PdfStamper 构造函数的第二个参数初始化的:

                PdfStamper stamper=new PdfStamper(reader,output);

不幸的是,output 已使用 iText 不喜欢的 null 进行了初始化。因此,还请提供适当的目标 OutputStream.