iText7:设置单选按钮值未按预期工作

问题描述 投票:0回答:1

我有一个在 InDesign 中使用单选按钮组创建的 PDF 文档。每个选择都有其价值。

PdfFormField field = AcroForm.GetField(fieldName);
field.SetValue(valueToSet);

在 InDesign 中设置指定的选项值不起作用。不会选择任何选项。仅当我输入“0”或“1”等字符串数字时它才有效,但不是实际值。我想用选择的值来设置该值。我不想使用选择的“索引”。

field.GetAppearanceStates();

如果我返回所有状态,我可以看到所有选择值、它们的索引和关闭状态。 我究竟做错了什么?如何使用 c# iText7 为选项值分配值?谢谢。

c# .net radio-button itext7 adobe-indesign
1个回答
0
投票

我遇到了同样的问题。我联系了 iText 支持,这是他们的回复:

我想对 iText 的实施决定提供一些见解 字段值“V”作为单选按钮字段的字符串,相反 遵循 PDF 规范的建议。虽然 PDF 规范 建议使用数字类型作为“V”条目,我们选择 在我们的实现中使用字符串值。这种方法确保 我们更广泛的设计中的一致性和兼容性。 通过扩展 来自公共表单字段对象的所有字段,包括“V”条目 一个字符串,我们保持统一的方法。

我针对itext7/8字符串值实现方式开发的是将一组单选按钮值映射到使用GetAppearanceStates()函数返回的字符串数值的过程。

首先要做的是获取状态:

List<string> appearanceStates = pdfFormFields.GetField("some field name").GetAppearanceStates().ToList();

检查返回的状态时,您会注意到,在 PDF 表单中找到所有单选按钮组值之后,您将首先看到一个 0,然后是一个“Off”值,后面跟着 1、2 等,具体取决于单选按钮的数量在您定位的单选按钮组中。您需要从返回的列表中删除“关闭”状态:

appearanceStates.Remove("Off");

接下来,您需要将单选按钮组值从字符串数值分解为两个单独的列表。两个列表应包含相同数量的项目:

List<string> radioButtonGroupValues = appearanceStates.Take(appearanceStates.Count / 2).ToList();
List<string> numericEquivalentList = appearanceStates.Skip(appearanceStates.Count / 2).ToList();

现在创建一个 Dictionary 对象并迭代两个列表。此过程将单选按钮值“映射”到 itext 在 GetAppearanceStates() 函数中返回的字符串数值:

Dictionary<string, string> dictionary = new Dictionary<string, string>();
for (int i = 0; i < radioButtonGroupValues .Count; i++)
{
    dictionary[radioButtonGroupValues [i]] = numericEquivalentList[i];
}

最后,您可以使用 linq 查询返回映射的字符串数值,其中键与您想要在 PDF 表单中设置为“On”的单选按钮值匹配:

string result = (from x in dictionary where x.Key == "radio button value" select x.Value).FirstOrDefault();

我将所有这些都放在一个类中,并将其变成了单例。无论单选按钮组中有多少个单选按钮,该类始终返回在 PDF 表单中准确选择单选按钮组中的单选按钮所需的字符串数值。我的类中某些变量的名称与上面显示的不同,但这是为了简化目的。为您自己的变量命名任何对您来说最有意义的名称。

   public class ITextRadioFieldUnifier
{
    private static ITextRadioFieldUnifier instance = null;
    private static object syncRoot = new object();

    public ITextRadioFieldUnifier() { }

    public static ITextRadioFieldUnifier Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new ITextRadioFieldUnifier();
                    }
                }
            }
            return instance;
        }
    }

    internal string ReturnExtendedString(PdfAcroForm pdfFormFields, string field, string value)
    {
        List<string> appearanceStates = pdfFormFields.GetField(field).GetAppearanceStates().ToList();
        appearanceStates.Remove("Off");
        Dictionary<string, string> map = CreateDictionary(TakeListFirstHalf(appearanceStates), SkipListFirstHalf(appearanceStates));
        return MapKeyValue(map, value);
    }

    private List<string> TakeListFirstHalf(List<string> states) => states.Take(states.Count / 2).ToList();

    private List<string> SkipListFirstHalf(List<string> states) => states.Skip(states.Count / 2).ToList();

    private Dictionary<string, string> CreateDictionary(List<string> valuesList, List<string> numericEquivalentList)
    {
        if (valuesList.Count != numericEquivalentList.Count)
        {
            throw new ArgumentException("Input lists must have the same number of elements.");
        }

        Dictionary<string, string> dictionary = new Dictionary<string, string>();
        for (int i = 0; i < valuesList.Count; i++)
        {
            dictionary[valuesList[i]] = numericEquivalentList[i];
        }

        return dictionary;
    }

    private string MapKeyValue(Dictionary<string, string> map, string value)
    {
        return (from x in map where x.Key == value select x.Value).FirstOrDefault();
    }
}

要使用该类,我可以在 .SetValue 中设置值时调用该函数,如下所示:

pdfFormFields.GetField("form field").SetValue(ITextRadioFieldUnifier.Instance.ReturnExtendedString(pdfFormFields, "form field", "value of your radio button"));

或者我可以像这样或类似的变体将其分解:

string result = ITextRadioFieldUnifier.Instance.ReturnExtendedString(pdfFormFields, "form field", "value of your radio button");
PdfFormField formField = pdfFormFields.GetField("form field");
formField.SetValue(result);

我确信有人可能已经开发出了更好的解决方案,但我在搜索过程中找不到任何东西。希望这对现在或将来可能处理此问题的人有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.