user4906165
user4906165

Reputation:

iTextSharp. How to get specific types from AcroFields? Like PushButtonField, RadioCheckField, etc

I am trying to cast AcroFields to the specific types so I can set properties on them.

When I call AcroFields.GetField(string name); all I get is a string.

When I call AcroFields.GetFieldItem(string name); I get an object but cannot cast it to the specific type.

I have also tried:

AcroFields.SetFieldProperty("myfield", "CheckType", RadioCheckField.TYPE_STAR, null);

This returned false every time.

To better explain my scenario:

I have an existing PDF ( I am NOT generating this file ).

There is a checkbox in it. I want to change the "CheckType" like this: myRadioCheckField.CheckType = RadioCheckField.TYPE_STAR

But since I cannot cast the AcroField to the specific type I cannot access that property "CheckType".

Is there a way to achieve this?

Please provide a working sample if possible.

Thank you.

Upvotes: 2

Views: 4258

Answers (3)

user4906165
user4906165

Reputation:

After some research I have come to the conclusion that at this point in time, with the current version of iTextSharp v5.5.7.0:

It is NOT possible to grab an AcroField and cast it back to the original class ( RadioCheckField ) that was used to generate the field in the first place.

So the specific classes like PushButtonField and RadioCheckField are only useful for generating a new PDF but not for editing an existing PDF.

Upvotes: 1

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

Your post contains two different questions. One question is easy to answer. The other question is impossible to answer.

Let's start with the easy question:

How to get specific types from AcroFields? Like PushButtonField, RadioCheckField, etc

This is explained in the FormInformation example, which is part of chapter 6 of my book:

PdfReader reader = new PdfReader(datasheet);
// Get the fields from the reader (read-only!!!)
AcroFields form = reader.AcroFields;
// Loop over the fields and get info about them 
StringBuilder sb = new StringBuilder();       
foreach (string key in form.Fields.Keys) {
    sb.Append(key);
    sb.Append(": ");
    switch (form.GetFieldType(key)) {
        case AcroFields.FIELD_TYPE_CHECKBOX:
            sb.Append("Checkbox");
            break;
        case AcroFields.FIELD_TYPE_COMBO:
            sb.Append("Combobox");
            break;
        case AcroFields.FIELD_TYPE_LIST:
            sb.Append("List");
            break;
        case AcroFields.FIELD_TYPE_NONE:
            sb.Append("None");
            break;
        case AcroFields.FIELD_TYPE_PUSHBUTTON:
            sb.Append("Pushbutton");
            break;
        case AcroFields.FIELD_TYPE_RADIOBUTTON:
            sb.Append("Radiobutton");
            break;
        case AcroFields.FIELD_TYPE_SIGNATURE:
            sb.Append("Signature");
            break;
        case AcroFields.FIELD_TYPE_TEXT:
            sb.Append("Text");
            break;
        default:
            sb.Append("?");
            break;
    }
    sb.Append(Environment.NewLine);
} 
// Get possible values for field "CP_1"
sb.Append("Possible values for CP_1:");
sb.Append(Environment.NewLine);
string[] states = form.GetAppearanceStates("CP_1");
for (int i = 0; i < states.Length; i++) {
    sb.Append(" - ");
    sb.Append(states[i]);
    sb.Append(Environment.NewLine);
}
// Get possible values for field "category"
sb.Append("Possible values for category:");
sb.Append(Environment.NewLine);
states = form.GetAppearanceStates("category");
for (int i = 0; i < states.Length - 1; i++) {
    sb.Append(states[i]);
    sb.Append(", ");
}
sb.Append(states[states.Length - 1]);

This code snippet stores the types of the fields in a StringBuilder, as well as the possible values of a radio field and a check box.

If you execute it on datasheet.pdf, you get form_info.txt as a result.

So far so good, but then comes the difficult question:

How do I find the check type? How do I change it?

That question reveals a lack of understanding of PDF. When we looked for the possible values of a check box (or radio button) in the previous answer, we asked for the different appearance states. These appearance states are small pieces of content that are expressed in PDF syntax.

For instance: take a look at the buttons.pdf form.

When we look at it on the outside, we see:

enter image description here

The check box next to "English" can be an empty square or a square with a pinkish background and a cross. Now let's take a look at the inside:

enter image description here

We see that this is the table check box, and we see that there are two appearance states: /Yes and /Off. What these states look like when selected, is described in a stream.

The stream of the /Off state is rather simple:

enter image description here

You immediately see that we are constructing a rectangle (re) and drawing it without filling it (S).

The /Yes state is slightly more complex:

enter image description here

We see that the fill color is being changed (rg), and that we stroke the rectangle in black and fill it using the fill color that was defined (B). Then we define two lines with moveTo (m) and lineTo (l) operations and we stroke them (S).

If you are proficient in PDF syntax, it is easy to see that we're drawing a cross inside a colored rectangle. So that answers your question on condition that you're proficient in PDF...

If you want to replace the appearance, then you have to replace the stream that draws the rectangle and the cross. That's not impossible, but it's a different question than the one you've posted.

Summarized: There is no such thing as a TYPE_STAR in the PDF reference (ISO-32000-1), nor in any PDF. If you have an existing PDF, you can not cast a check box or radio button to a RadioCheckField. You could try to reconstruct the RadioCheckField object, but if you'd want to know if a check box is visualized using a check mark, a star,... then you have to interpret the PDF syntax. If you don't want to do that, you can't create the "original" RadioCheckField object that was used to create the PDF due to the lack of ready-to-use information in the PDF.

Upvotes: 8

Jonathan Alfaro
Jonathan Alfaro

Reputation: 4376

This cannot be done.

As far as I know iTextSharp does not support casting from AcroField back to the orginal class ( RadioCheckField ) that was used to generate the field.

You would have to write your own code to parse and inspect the PDF to achieve this.

Upvotes: 0

Related Questions