2

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.

3 Answers3

8

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.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • 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. –  Oct 21 '15 at 20:04
  • 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. – Bruno Lowagie Oct 21 '15 at 20:26
  • The second part of your comment confirms that you didn't understand a word of what I wrote: 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 and check box (or radio button) appearances. – Bruno Lowagie Oct 21 '15 at 20:27
  • 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 –  Oct 22 '15 at 01:19
  • 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. –  Oct 22 '15 at 01:20
  • You see the so called questions that you are saying I made "How do I find the check type? How do I change it?" are questions YOU made. I was very clear in my post as what I need. –  Oct 22 '15 at 01:22
  • 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". Wo 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 –  Oct 22 '15 at 01:26
  • Even further your answer did not even provide an alternative as you ended up saying "That's not impossible, but it's a different question than the one you've posted." and did not provide a C# example using iTextSharp. If I could down vote your answer I would. –  Oct 22 '15 at 01:29
  • I write: *Of course GetFieldType returns an int* and you say "]GetFieldType simple returns an INT" thus confirming what I have just said. You say that the int is "defined as a constant in the library" and that's exactly what you see in my code sample: `AcroFields.FIELD_TYPE_CHECKBOX`, `AcroFields.FIELD_TYPE_COMBO`, etc... Your error is that you think that the int refers to `RadioCheckField.TYPE_STAR`, etc... Unfortunately, your attitude doesn't allow you to admit the error you're making. That's sad. It will take a long time before you have a reputation as high as mine. – Bruno Lowagie Oct 22 '15 at 02:09
  • I have never stated that "the int refers to RadioCheckField.TYPE_STAR" That's is just a lie. Second I do not care if you made iTextSharp. Your personal experience is an ad-verecundiam fallacy and does not answer my question. You started by saying "your question shows your lack of understanding". You cannot prove my lack of understanding. If I wanted to write my own PDF Library then I would not be asking how to do it with iTextSharp. How to cast an AcroField back to the original class RadioCheckButton that was used by iTextSharp to generated it in the first place. You did not answer sorry! –  Oct 22 '15 at 15:20
  • 1
    The class `RadioCheckButton` contains a lot of information that is used to create a check box or a radio button. However, once the PDF with this check box or radio button is created, **plenty of this information is lost.** Think of a `PdfPTable` that is rendered: in the PDF, you can no longer retrieve that table, because it has been reduced to text and lines at absolute positions. The same goes for `TYPE_STAR`: in the resulting PDF, there is no `TYPE_STAR`, there are two appearances that use PDF syntax. You need to examine that syntax if you want to reconstruct the original `RadioCheckField`. – Bruno Lowagie Oct 22 '15 at 15:29
  • 1
    To summarize: 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 case 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*. – Bruno Lowagie Oct 22 '15 at 15:40
  • If you would have used that last comment as answer I would have marked it as an answer. –  Oct 22 '15 at 15:47
  • Read the rules on StackOverflow. It is *mandatory* that I link to your profile page on StackOverflow. It would be illegal *not* to mention your name as all content on StackOverflow is licensed under the Creative Commons Attribution mandatory... – Bruno Lowagie Oct 23 '15 at 23:46
  • As you doubt everything I say, here are the [Terms of Service](http://stackexchange.com/legal/terms-of-service). Read article 3 c: *You will ensure that any such use of Subscriber Content visually display or otherwise clearly indicate the author names for every question and answer so used.* (In other words: you were wrong once again.) I wonder: how are you using iTextSharp? If you don't understand the CC, chances are you don't understand the AGPL either. Maybe you're infringing the copyright of iTextSharp... Can you check? – Bruno Lowagie Oct 23 '15 at 23:59
1

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.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
0

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.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
Jonathan Alfaro
  • 4,013
  • 3
  • 29
  • 32
  • 1
    Bruno you sent me a private message saying I stole someones answer. And called me "lame". That is 2 times you insulted me for no reason. I did not steal anyones answer. And you edited my answer to look almost likes yours. I will report you for being abusive – Jonathan Alfaro Oct 25 '15 at 15:42