I\'m working on dynamically filling in the fields on a pdf document using ITextSharp. I\'d like to be able to determine the \"export value\" of the checkbox is from the cod
I couldn't get the answer Mark to work for me because the appearanceDict was always null. Here is a method I wrote that works for the CheckBox and RadioButton controls on the forms I'm dealing with.
private static string GetAnswerValue(AcroFields.Item f, int i)
{
var widg = f.GetWidget(i);
if (widg == null)
return null;
var ap = widg.GetAsDict(PdfName.AP);
if (ap == null)
return null;
//PdfName.D also seems to work
var d = ap.GetAsDict(PdfName.N);
if (d == null)
return null;
var e = d.Keys.FirstOrDefault(n => !n.Equals(PdfName.OFF));
if (e == null)
return null;
return e.ToString().Substring(1);
}
Okay, you need to check the low-level PDF objects for the appropriate values. You can look up said values in the PDF Reference (chapter 12: Interactive Features, section 7: Interactive Forms).
In particular (and in Java):
AcroFields.Item item = acroFields.getFieldItem(fldName);
PdfDictionary valueDict = item.getValue(0);
PdfDictionary appearanceDict = valueDict .getAsDict(PdfName.AP);
if (appearanceDict != null) {
PdfDictionary normalAppearances = appearanceDict.getAsDict(PdfName.N);
// /D is for the "down" appearances.
// if there are normal appearances, one key will be "Off", and the other
// will be the export value... there should only be two.
if (normalAppearances != null) {
Set<PdfName> keys = normalAppearances .getKeys();
for (PdfName curKey : keys) {
if (!PdfName.OFF.equals(curKey)) {
return curKey.toString(); // string will have a leading '/' character
}
}
}
}
// if that doesn't work, there might be an /AS key, whose value is a name with
// the export value, again with a leading '/'
PdfName curVal = valueDict.getAsName(PdfName.AS);
if (curVal != null) {
return curVal.toString();
}
Something like that. The usual "I just wrote this in the edit box here" provisions apply, but that should be good to go. I write a distressingly large amount of low level iText code.
The best way I found to set a checkbox is:
void SetCB(AcroFields fields, string F)
{
try
{
fields.SetField(F, fields.GetFieldItem(F).GetValue(0).GetAsDict(PdfName.AP).GetAsDict(PdfName.N).Keys.Single().ToString().TrimStart('/'));
} catch { }
}
error: Sequence contains more than one element
e.g:
PdfReader reader = new PdfReader("c:\\qqq\\fl100Y2.pdf");// formFile);
using (PdfStamper stamper = new PdfStamper(reader, new FileStream("c:\\qqq\\fl100Ynew.pdf", FileMode.Create)))
{
AcroFields fields = stamper.AcroFields;
bool set = fields.SetFieldProperty("FillText156", "textsize", 10.0f, null);
SetCB(fields, "CheckBox24");
SetCB(fields, "CheckBox24by");
fields.SetField("FillText156", "John Doe");
// flatten form fields and close document
stamper.FormFlattening = true;
stamper.Close();
}
This was the final method I used to get it working based on the others:
public string GetCheckBoxExportValue(AcroFields fields, string cbFieldName)
{
AcroFields.Item item = fields.GetFieldItem(cbFieldName);
if (item.values.Count > 0)
{
PdfDictionary valueDict = item.values[0] as PdfDictionary;
PdfDictionary appDict = valueDict.GetAsDict(PdfName.AP);
if (appDict != null)
{
PdfDictionary normalApp = appDict.GetAsDict(PdfName.N);
foreach (PdfName curKey in normalApp.Keys)
{
if (!PdfName.OFF.Equals(curKey))
{
// string will have a leading '/' character
return curKey.ToString();
}
}
}
PdfName curVal = valueDict.GetAsName(PdfName.AS);
if (curVal != null)
{
return curVal.ToString();
}
}
return null;
}