0

Hey so I am trying to use iText to get Strings added by the user and then add them to a fillable PDF which i imported into the app. However, my app does not recognize the pre-described strings I am adding. I will just add some snippets of the code so anyone can tell me whats wrong. Sorry if it may sound like a weak question, but this is my first time using iText.

This is my 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();

}


}

The line of code that seems to have issues are when I try to set the fields in the PDF with each editText in my app.

acroFields.setField("fullnameorinitials",one);

The error is on the string value (one). Please any kind of reproductive help is appreciated!

droidnoob
  • 333
  • 5
  • 17
  • 1
    *The error is on the string value (one)* - which error exactly? Furthermore, you do not close the `stamper`. Thus, even without some error your code won't work as expected. – mkl Sep 18 '15 at 04:22
  • 1
    Show us the form! Maybe there is no field with name `fullnameorinitials` in that form (in which case the value of `one` will never be added). – Bruno Lowagie Sep 18 '15 at 07:15
  • @mkl it said something about not being able to resolve the method one, but one is a string – droidnoob Sep 18 '15 at 07:34
  • @BrunoLowagie i labelled it accordingly, the error wasn't on the name but the value, one – droidnoob Sep 18 '15 at 07:35
  • @mkl i should't surround the stamper with try-catch ? – droidnoob Sep 18 '15 at 07:37
  • The only place where you use `one` as if it were a method instead of a variable is here: `newCustomer.one(editText.getText().toString());` but that part is commented out. Your question is incomplete and therefore can't be answered. You should complete your question by showing the stack trace and the line number where the error occurs. Also: this is **not** an iText question if your compiler complains about a variable being a method. `one` is a *method* or *variable* **you** defined and used (probably incorrectly). – Bruno Lowagie Sep 18 '15 at 07:44
  • *it said something about not being able to resolve the method one, but one is a string* - Actually I see **no declaration** of `one` at all in `Main` itself (where you use it), merely in the inner class `Customer`. So unless you dropped the declaration when copying to your question, thre is bound to be some error message about missing `one`. – mkl Sep 18 '15 at 07:48
  • *i should't surround the stamper with try-catch* - who said that? I merely indicated that you should call `stamper.close()` after applying changes to the stamper. – mkl Sep 18 '15 at 07:50
  • @mkl so do i declare it in both the inner class and the main class? is that what you're suggesting? – droidnoob Sep 18 '15 at 07:51
  • @BrunoLowagie yes thats the line thats giving me issues, i just commented it out because I didn't want the red in my program, but i mustve forgotten to add it back. I tagged it to iText because its my first time using it and I do not know what I'm doing wrong – droidnoob Sep 18 '15 at 07:53
  • What is your intention with that line? There is no method named `one` in your `Customer` class, hence the error. You are confusing SO readers by also introducing a `String` variable named `one`. – Bruno Lowagie Sep 18 '15 at 08:03
  • As you don't **set** that variable `one` anywhere in your `Main` code, I don't know where you *should* **declare** it either. In my eyes it is totally unclear what you *expect* your code to do. – mkl Sep 18 '15 at 08:07
  • when the user fills the form in the app, the code takes the user's input and then adds it to the pdf form i added to the app, so it can be mailed, thats basically it @mkl – droidnoob Sep 18 '15 at 08:43
  • 1
    How about changing the `setField` calls to `acroFields.setField("fullnameorinitials", editText.getText().toString())` and `acroFields.setField("agedob", editText2.getText().toString())` respectively. and don't forget the `stamper.close()` after that. – mkl Sep 18 '15 at 08:56
  • 1
    (You can of course slip in a `Customer` bean for separation of concerns, but in that case use sensible, member names independent from view fields, e.g. `fullName` instead of `one`.) – mkl Sep 18 '15 at 09:05
  • it worked! thank you so much! @mkl – droidnoob Sep 18 '15 at 09:19
  • Ok, I'll make that an actual answer. – mkl Sep 18 '15 at 12:06

1 Answers1

2

There are two issues in the code, one concerning variable scopes preventing compilation and one concerning iText API use preventing proper result PDFs.

Variable scopes

Variables must be declared and visible in the scope in which they are used. This was not the case for one and two in the onClick implementation in the anonymous inner class based on View.OnClickListener constructed in Main.onCreate:

@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);
            }
            [...]
        }
    });
}

This code can use all static Main variables, all non-static member variables of the Main instance at hand, all final variables declared in onCreate before the instantiation of the OnClickListener, all static variables of the anonymous class and all non-static ones of the instance at hands, and all variables in onClick before the use of one and two.

The only variables one and two declaration is in the other inner class, Customer.

Assuming the values those Customer class members would have been initialized with, to be the desired data in onClick, the compilation failure can be fixed like this:

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

(You can of course slip in a Customer bean for separation of concerns, but in that case please use sensible, member names independent from view fields, e.g. fullName instead of one.)

Now the code can be compiled but it still does not necessarily produce the correct result. Thus:

iText API use

In the code above, PdfStamper is instantiated, then some fields are set with it, then nothing... The iText API contract, on the other hand, expects PdfStamper instances to be closed after use: During close the PDF output is finalized.

Thus:

            [...]
            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();
            }
            [...]

Furthermore iText PdfStamper expects some target to write to, In the original code the target is initialized from the second parameter of the PdfStamper constructor used:

                PdfStamper stamper=new PdfStamper(reader,output);

Unfortunately, output has been initialized with null which iText will not like. Thus, please also supply a proper target OutputStream.

mkl
  • 90,588
  • 15
  • 125
  • 265