简体   繁体   English

使用iTextSharp获取复选框的导出值

[英]Get the export value of a checkbox using iTextSharp

I'm working on dynamically filling in the fields on a pdf document using ITextSharp. 我正在使用ITextSharp动态填写pdf文档中的字段。 I'd like to be able to determine the "export value" of the checkbox is from the codebehind in order to determine what value to send to this checkbox if it should be checked. 我希望能够确定复选框的“导出值”来自代码隐藏,以便确定在应该检查时向该复选框发送什么值。 Most of the documents I've worked with in the past had the same export value for every check box but the one I'm currently working with varies from checkbox to checkbox. 我过去使用过的大多数文档对每个复选框都有相同的导出值,但我正在使用的那个文件因复选框而异。 I could go through all of the text boxes and make them consistent but it would save a lot of time in the future if I could just determine what the export value of these checkboxes are at runtime and set them accordingly. 我可以浏览所有文本框并使它们保持一致但如果我可以确定这些复选框在运行时的导出值并相应地设置它们将在未来节省大量时间。

Thanks in advance! 提前致谢!

I tried to implement the solution below in C# and ended up with the following code: 我尝试在C#中实现下面的解决方案,最后得到以下代码:

 public string GetCheckBoxExportValue(AcroFields pdfDocument, string checkBoxFieldName)
    {
        AcroFields.Item item = pdfDocument.GetFieldItem(checkBoxFieldName);
        if (item.values.Count > 0)
        {
            PdfDictionary valueDict = item.GetValue(0);

            PdfDictionary appearanceDict = valueDict.GetAsDict(PdfName.AP);

            // if there's an appearance dict at all, one key will be "Off", and the other
            // will be the export value... there should only be two.
            if (appearanceDict != null)
            {


                foreach (PdfName curKey in appearanceDict.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();
            }

        }
        //return null if you get this far
            return null;

    }

This just returns "/D" every single time. 这只是每次返回“/ D”。 I'm not sure if the approach needs to be different in C# or if I'm just missing something. 我不确定C#中的方法是否需要不同,或者我是否只是缺少某些东西。

Okay, you need to check the low-level PDF objects for the appropriate values. 好的,您需要检查低级PDF对象以获取适当的值。 You can look up said values in the PDF Reference (chapter 12: Interactive Features, section 7: Interactive Forms). 您可以在PDF参考中查找所述值(第12章:交互式功能,第7节:交互式表单)。

In particular (and in Java): 特别是(和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. 我写了一个令人沮丧的大量低级iText代码。

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 错误:序列包含多个元素

eg: 例如:

       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;
    }

I couldn't get the answer Mark to work for me because the appearanceDict was always null. 我无法得到答案Mark为我工作,因为appearanceDict总是为null。 Here is a method I wrote that works for the CheckBox and RadioButton controls on the forms I'm dealing with. 这是我编写的一个方法,适用于我正在处理的表单上的CheckBox和RadioButton控件。

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM