简体   繁体   English

使用 PDFSharp 填充 PdfRadioButtonField

[英]Populate PdfRadioButtonField using PDFSharp

I'm using PDFSharp version 1.50.4740-beta5 from http://www.pdfsharp.net which I installed from NuGet.我使用的是来自http://www.pdfsharp.net 的PDFSharp 1.50.4740-beta5 版本,我从 NuGet 安装了该版本。

I'm able to fill text form fields and checkbox form fields but I can't get radio buttons to work at all.我可以填写文本表单字段和复选框表单字段,但我根本无法使用单选按钮。 I don't get an error.我没有收到错误。 SelectedIndex is -1 before and after I set it to 1. SelectedIndex 在我将其设置为 1 之前和之后都是 -1。

Several at articles on Stack Overflow have helped me to get this far. Stack Overflow 上的几篇文章帮助我走到了这一步。 Has anyone successfully populated radio button form fields using this product?是否有人使用此产品成功填充了单选按钮表单字段? Here is a link to the sample PDF: http://www.myblackmer.com/bluebook/interactiveform_enabled.pdf这是示例 PDF 的链接: http : //www.myblackmer.com/bluebook/interactiveform_enabled.pdf

(Before you suggest iTextPdf, I've already evaluated it and Aspose.PDF and they are not practical) (在你推荐 iTextPdf 之前,我已经评估过它和 Aspose.PDF 并且它们不实用)

        //using PdfSharp.Pdf.IO;
        //using PdfSharp.Pdf;
        //using PdfSharp.Pdf.AcroForms;
        string fileName = "x:\\interactiveform_enabled.pdf";
        PdfSharp.Pdf.PdfDocument pdfDocument = PdfReader.Open(fileName);

        //The populated fields are not visible by default
        if (pdfDocument.AcroForm.Elements.ContainsKey("/NeedAppearances"))
        {
            pdfDocument.AcroForm.Elements["/NeedAppearances"] = new PdfBoolean(true);
        }
        else
        {
            pdfDocument.AcroForm.Elements.Add("/NeedAppearances", new PdfBoolean(true));
        }

        PdfRadioButtonField currentField = (PdfRadioButtonField)(pdfDocument.AcroForm.Fields["Sex"]);
        currentField.ReadOnly = false;
        currentField.SelectedIndex = 1;

        pdfDocument.Flatten();
        pdfDocument.Save("x:\\interactiveform_enabled_2.pdf");

The following worked for me:以下对我有用:

  1. Find out the possible values of the radio buttons, eg using a PDF tool找出单选按钮的可能值,例如使用 PDF 工具
  2. Use the Value property with a PdfName instance (not a PdfString !)Value属性与PdfName实例(不是PdfString !)一起使用
  3. Use the prefix / before the value name在值名称前使用前缀/

Example, if you want to set the option "choice1" selected:例如,如果要设置选项“choice1”被选中:

var radio = (PdfRadioButtonField)form.Fields["MyRadioButtonField"];
radio.Value = new PdfName("/choice1");

I found the solution at https://forum.pdfsharp.net/viewtopic.php?f=2&t=632我在https://forum.pdfsharp.net/viewtopic.php?f=2&t=632找到了解决方案

Since this is #1 in a Google search for "PDFSharp radio buttons", figured I'd share what seems to be working for me.由于这是在 Google 搜索“PDFSharp 单选按钮”中排名第一,我想我会分享似乎对我有用的内容。

I created extension functions for the PdfRadioButtonField object that:我为PdfRadioButtonField对象创建了扩展函数:

  • Gets all option values and their indexes获取所有选项值及其索引
  • Sets the value for a radio field by index number通过索引号设置单选字段的值
  • Sets the value for a radio field by value按值设置单选字段的值

In the following examples, ErPdfRadioOption is:在以下示例中, ErPdfRadioOption是:

public class ErPdfRadioOption
{
    public int Index { get; set; }
    public string Value { get; set; }
}

Get all available options for a radio field获取无线电场的所有可用选项


public static List<ErPdfRadioOption> FindOptions(this PdfRadioButtonField source) {
    if (source == null) return null;
    List<ErPdfRadioOption> options = new List<ErPdfRadioOption>();

    PdfArray kids = source.Elements.GetArray("/Kids");

    int i = 0;
    foreach (var kid in kids) {
        PdfReference kidRef = (PdfReference)kid;
        PdfDictionary dict = (PdfDictionary)kidRef.Value;
        PdfDictionary dict2 = dict.Elements.GetDictionary("/AP");
        PdfDictionary dict3 = dict2.Elements.GetDictionary("/N");

        if (dict3.Elements.Keys.Count != 2)
            throw new Exception("Option dictionary should only have two values");

        foreach (var key in dict3.Elements.Keys)
            if (key != "/Off") { // "Off" is a reserved value that all non-selected radio options have
                ErPdfRadioOption option = new ErPdfRadioOption() { Index = i, Value = key };
                options.Add(option);
            }
        i++;
    }

    return options;
}

Usage用法

PdfDocument source;
PdfAcroField field = source.AcroForm.Fields[...]; //name or index of the field
PdfRadioButtonField radioField = field as PdfRadioButtonField;
return radioField.FindOptions();

Result (JSON)结果 (JSON)


[
  {
    "Index": 0,
    "Value": "/Choice1"
  },
  {
    "Index": 1,
    "Value": "/Choice2"
  },
  {
    "Index": 2,
    "Value": "/Choice3"
  }
]

Set the option for a radio field by index按索引设置无线电字段的选项

You'd think this is what the SelectedIndex property should be for... but apparently not.您可能会认为这是SelectedIndex属性的用途……但显然不是。


public static void SetOptionByIndex(this PdfRadioButtonField source,int index) {
    if (source == null) return;
    List<ErPdfRadioOption> options = source.FindOptions();
    ErPdfRadioOption selectedOption = options.Find(x => x.Index == index);
    if (selectedOption == null) return; //The specified index does not exist as an option for this radio field
    
    // https://forum.pdfsharp.net/viewtopic.php?f=2&t=3561
    PdfArray kids = (PdfArray)source.Elements["/Kids"];
    int j = 0;
    foreach (var kid in kids) {
        var kidValues = ((PdfReference)kid).Value as PdfDictionary;
        //PdfRectangle rectangle = kidValues.Elements.GetRectangle(PdfAnnotation.Keys.Rect);
        if (j == selectedOption.Index)
            kidValues.Elements.SetValue("/AS", new PdfName(selectedOption.Value));
        else
            kidValues.Elements.SetValue("/AS", new PdfName("/Off"));
        j++;
    }
}

Note: This depends on the FindOptions() function above.注意:这取决于上面的 FindOptions() 函数。

Usage用法

PdfDocument source;
PdfAcroField field = source.AcroForm.Fields[...]; //name or index of the field
PdfRadioButtonField radioField = field as PdfRadioButtonField;
radioField.SetOptionByIndex(index);

Set the option for a radio field by value按值设置单选字段的选项


public static void SetOptionByValue(this PdfRadioButtonField source, string value) {
    if (source == null || string.IsNullOrWhiteSpace(value)) return;
    if (!value.StartsWith("/", StringComparison.OrdinalIgnoreCase)) value = "/" + value; //All values start with a '/' character
    List<ErPdfRadioOption> options = source.FindOptions();
    ErPdfRadioOption selectedOption = options.Find(x => x.Value == value);
    if (selectedOption == null) return; //The specified index does not exist as an option for this radio field
    source.SetOptionByIndex(selectedOption.Index);
}

Note: This depends on the FindOptions() and SetOptionByIndex() functions above.注意:这取决于上面的FindOptions()SetOptionByIndex()函数。

Based on this post in the PDFsharp forum: https://forum.pdfsharp.net/viewtopic.php?f=2&t=3561#p11386基于 PDFsharp 论坛中的这篇文章: https ://forum.pdfsharp.net/viewtopic.php ? f =2& t = 3561#p11386

Using PDFsharp version 1.50.5147使用 PDFsharp 版本 1.50.5147

Based on Chris's answer, the salient point is that you have to set the value for all options to \\Off while setting the option's value you want to the \\Choice.根据克里斯的回答,重点是您必须将所有选项的值设置为 \\Off,同时将您想要的选项值设置为 \\Choice。 To that end, you can have a simple function like:为此,您可以拥有一个简单的功能,例如:

    //sets a radio button option by setting the index and value and turning the others off
    static void setRadioOption (PdfRadioButtonField field, int option, string optvalue)
    {
        PdfArray kids = (PdfArray)field.Elements["/Kids"];
        int j = 0;
        foreach (var kid in kids)
        {
            var kidValues = ((PdfReference)kid).Value as PdfDictionary;
            if (j == option)
                kidValues.Elements.SetValue("/AS", new PdfName(optvalue));
            else
                kidValues.Elements.SetValue("/AS", new PdfName("/Off"));
            j++;
        }
    }

Is it me you're looking for?你要找的是我吗?

private static void SetPdfRadiobutton(PdfDocument document, string fieldname, string newvalue, int item)
    {
        PdfRadioButtonField field = (PdfRadioButtonField)document.AcroForm.Fields[fieldname];
        PdfArray items = (PdfArray)field.Elements["/Kids"];

        for (int i = 0; i < items.Elements.Count; i++)
        {
            PdfDictionary keys = ((PdfReference)items.Elements[i]).Value as PdfDictionary;
            keys.Elements.SetValue("/AS", i == item ? new PdfName(newvalue) : new PdfName("/Off"));
        }

        field.ReadOnly = true;
    }

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

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