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

Tags: formsInspect fieldsfield typescheck boxradio fieldtext fieldiText 5

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?

Posted on StackOverflow on Oct 20, 2015 by anonymous

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:

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 the following result:

title: Text
category: Radiobutton
director: Text
MA_2: Checkbox
CP_2: Checkbox
GP_3: Checkbox
MA_3: Checkbox
GP_8: Checkbox
year: Text
CP_1: Checkbox
GP_4: Checkbox
CP_3: Checkbox
GP_7: Checkbox
duration: Text
Possible values for CP_1:
- Off
- Yes
Possible values for category:
Off, comp, fest, fdir, kubr, kuro, zha, lee, kim, toro, worl, fran, scan, s-am, spec, teen, anim, kauf, rive, hero

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 a form with some radio buttons and check boxes.

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

Form with radio buttons and check boxes
Form with radio buttons and check boxes

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:

Looking under the hood of a form
Looking under the hood of a form

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:

Syntax off state
Syntax off state

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

The /Yes state is slightly more complex:

Syntax yes state
Syntax yes state

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.

GetFieldType returns an int not the actual type. What I need is to be able to get the actual Type. I do not care about PDF syntax because my question is about iTextSharp. I can do it easily like this myRadioCheckField.CheckType = RadioCheckField.TYPE_STAR when I generate the PDF. In this case I already have a PDF and need to obtain the field cast it to it's original type then access its properties. I do not need to know the original type. I already know it. What I need is to obtain the field and cast it to its original Type. (anonymous)

You didn't read my answer, did you? Of course GetFieldType returns an int. In the code sample I provided, a switch / case resolves the int to the type. So the first part of your comment is irrelevant. The second part of your comment confirms that you didn't understand my answer: there is no such thing as a CheckType in PDF. CheckType is there for your convenience when you create a PDF, but once the PDF is created, there is no longer a trace of the CheckType. iTextSharp is a PDF library, so you should care about PDF syntax. Consult ISO-32000-1 and you'll discover that your question is wrong: there is no such thing as a CheckType in an existing PDF. You are confusing field types (such as text field, button,...) and field appearances (such as stars, check marks,...).

Once again the one that did not understand the question is you. First GetFieldType does not resolve to the particular type it simple returns an int which is defined as a constant in the library. Second I do not care about lower level complexity. If you do not know how to achieve what I need then you do not have the answer. I will be very punctual: It has to be done with iTextSharp; I need to convert the field back to the original type that was used by iTextSharp to generate the PDF in the first place... got it? I do not need nor care to know about lower level stuff like PDF Syntax So if you do not know then just say you do not know. If you think it is not possible then the answer is "it is not possible"; otherwise you have not answered the question. I did not come looking for PDF syntax information. I came looking for specific code sample using iTextSharp any other answer is not for me. By the way CheckType is a property of the RadioCheckButton in iTextSharp. How iTextSharp works under the hood is not of my interest. If you do not know how to CAST an AcroField back to the RadioCheckButton class then your answer is not for me. If you read my post it starts with "I am trying to cast AcroFields to the specific types". What part of that don't you get? Your answer does not answer my question. As a matter of fact I already knew everything you mentioned and still that does not solve my problem. (anonymous)

Then the rant goes on and on, with the OP bragging about his experience and showing off with the use of Latin words. However that doesn't change the simple truth:

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.

If you ever post a question and you want an answer, please take into account that answers are giving on a voluntary basis and that it's usually counter-productive to insult the people who are willing to spend some time to help you out. Saying things like I do not care about PDF syntax because my question is about iTextSharp. and I will be very punctual: It has to be done with iTextSharp usually isn't wise.