使用 iTextSharp 将表单元素添加到表格中



我正在尝试创建一个PDF文档,该文档本质上是表格格式的用户列表。我需要表格中包含复选框。到目前为止,我分别拥有表格和复选框,但我找不到在表格中获取复选框的方法。我想我需要使用 AddCell() 方法添加它们。

这是我的代码:

static void Main(string[] args)
    {
        // create the document, filestream, writer
        Document doc = new Document(PageSize.LETTER);
        FileStream file = new FileStream(@"C:UserstestUser List.pdf", FileMode.OpenOrCreate);
        PdfWriter writer = PdfWriter.GetInstance(doc, file);
        try
        {
            // metadata
            doc.AddAuthor("Test User");
            doc.AddCreator("Test Document");
            doc.AddKeywords("Test Document");
            doc.AddSubject("Test Document");
            doc.AddTitle("Test Document - Test User");
            // open up the PDF document
            doc.Open();
            PdfContentByte cb = writer.DirectContent;
            Font _bf = new Font(Font.FontFamily.HELVETICA, 9);
            // create a table
            PdfPTable table = new PdfPTable(3);
            PdfPCell cell = new PdfPCell(new Phrase("User List"));
            PdfFormField field = PdfFormField.CreateCheckBox(writer);
            field.SetWidget(new Rectangle(40, 500, 60, 530), PdfAnnotation.HIGHLIGHT_INVERT);
            field.SetFieldFlags(PdfAnnotation.FLAGS_PRINT);
            field.FieldName = "Delete";
            writer.AddAnnotation(field);
            cell.Colspan = 3;
            cell.HorizontalAlignment = 0; //0 = left, 1 = center, 2 = right
            cell.VerticalAlignment = 1;
            table.AddCell("No.");
            table.AddCell("Users");
            table.AddCell("Delete");
            // create form fields
            PdfAppearance[] onOff = new PdfAppearance[2];
            Rectangle rect;
            PdfFormField checkbox;
            RadioCheckField _checkbox;
            onOff[0] = cb.CreateAppearance(10, 10);
            onOff[0].Rectangle(1, 1, 8, 8);
            onOff[0].Stroke();
            onOff[1] = cb.CreateAppearance(10, 10);
            onOff[1].SetRGBColorFill(255, 128, 128);
            onOff[1].Rectangle(1, 1, 8, 8);
            onOff[1].FillStroke();
            onOff[1].MoveTo(1, 1);
            onOff[1].LineTo(9, 9);
            onOff[1].MoveTo(1, 9);
            onOff[1].LineTo(9, 1);
            onOff[1].Stroke();
            for (int i = 0; i < 5; i++)
            {
                table.AddCell(i.ToString());
                table.AddCell("User " + i);
                //rect = new Rectangle(400, 675 - i*40, 415, 663 - i*40);
                rect = new Rectangle(400, 735 - i * 40, 415, 723 - i * 40);
                _checkbox = new RadioCheckField(writer, rect, "User "+(i+1), "Yes");
                checkbox = _checkbox.CheckField;
                checkbox.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", onOff[0]);
                checkbox.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "On", onOff[1]);
                writer.AddAnnotation(checkbox);
                // this is where I am trying to add the checkbox to the table
                // what can I add to AddCell() to make the checkbox show up?
                table.AddCell();
                //ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("User " + (i + 1), _bf), 50, 665 - i * 40, 0);
            }
            cb = writer.DirectContent;
            doc.Add(table);
        }
        catch(DocumentException dex)
        {
            throw (dex);
        }
        finally
        {
            // close
            doc.Close();
            writer.Close();
            file.Close();
        }
    }

有没有办法使用iTextSharp来做到这一点?也许有更好的库可以使用?

我将参考iText网站,展示如何将字段传递给自定义IPdfPCellEvent实现,以及如何创建该自定义类并在下面的C#中重新创建它。

首先,创建一个实现IPdfPCellEvent的类:

public class ChildFieldEvent : IPdfPCellEvent {
    /** A parent field to which a child field has to be added. */
    protected PdfFormField parent;
    /** The child field that has to be added */
    protected PdfFormField kid;
    /** The padding of the field inside the cell */
    protected float padding;
    /**
     * Creates a ChildFieldEvent.
     * @param parent the parent field
     * @param kid the child field
     * @param padding a padding
     */
    public ChildFieldEvent(PdfFormField parent, PdfFormField kid, float padding) {
        this.parent = parent;
        this.kid = kid;
        this.padding = padding;
    }
    /**
     * Add the child field to the parent, and sets the coordinates of the child field.
     */
    public void CellLayout(PdfPCell cell, iTextSharp.text.Rectangle rect, PdfContentByte[] cb) {
        parent.AddKid(kid);
        kid.SetWidget(new iTextSharp.text.Rectangle(
                                                    rect.GetLeft(padding),
                                                    rect.GetBottom(padding),
                                                    rect.GetRight(padding),
                                                    rect.GetTop(padding)
                                                    ),
                                                    PdfAnnotation.HIGHLIGHT_INVERT
                                                    );
    }
}

然后,只需在应该包含字段的任何单元格上设置CellEvent即可。

//File to create
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Standard PDF creation, nothing special here
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
    using (var doc = new Document()) {
        using (var writer = PdfWriter.GetInstance(doc, fs)) {
            doc.Open();
            //Create a root form object that we'll add "children" to. This way we don't have to add each "child" annotation to the writer
            var root = PdfFormField.CreateEmpty(writer);
            root.FieldName = "root";
            //Create a two column table
            var t = new PdfPTable(2);
            //Add a basic cell
            t.AddCell("First Name");
            //Create our textfield, the rectangle that we're passing in is ignored and doesn't matter
            var tf = new TextField(writer, new iTextSharp.text.Rectangle(0, 0), "first-name");
            //Create a new cell
            var cell = new PdfPCell();
            //Set the cell event to our custom IPdfPCellEvent implementation
            cell.CellEvent = new ChildFieldEvent(root, tf.GetTextField(), 1);
            //Add the cell to our table
            t.AddCell(cell);
            //Add the table to the document
            doc.Add(t);
            //IMPORTANT! Add the root annotation to the writer which also adds all of the child annotations
            writer.AddAnnotation(root);

            //Clean up
            doc.Close();
        }
    }
}

最新更新