Create FormField in PDF in C#, VB.NET

PDF form is often used to display, catch and edit data. People can fill blanks with data and submit data to server. Spire.PDF enables users to add fields and create form in PDF document.

Note: Please make sure Spire.PDF and Visual Studio are correctly installed on system.

Step 1: Create a PDF document and set margin for it

[C#]
            //Create a pdf document.
            PdfDocument doc = new PdfDocument();

            //margin
            PdfUnitConvertor unitCvtr = new PdfUnitConvertor();
            PdfMargins margin = new PdfMargins();
            margin.Top = unitCvtr.ConvertUnits(2.54f, PdfGraphicsUnit.Centimeter, PdfGraphicsUnit.Point);
            margin.Bottom = margin.Top;
            margin.Left = unitCvtr.ConvertUnits(3.17f, PdfGraphicsUnit.Centimeter, PdfGraphicsUnit.Point);
            margin.Right = margin.Left;

Step 2: Set document template

There are three parameters passed to this method: document, page size and margin. In this step, SetDocumentTemplate has been declared for use in main method conveniently.

Draw PDF cover

[C#]
 SetDocumentTemplate(doc, PdfPageSize.A4, margin);
Details of SetDocumentTemplate Method

1). Set template left space and top space.

[C#]
            PdfPageTemplateElement leftSpace
                = new PdfPageTemplateElement(margin.Left, pageSize.Height);
            doc.Template.Left = leftSpace;

            PdfPageTemplateElement topSpace
                = new PdfPageTemplateElement(pageSize.Width, margin.Top);
            topSpace.Foreground = true;
            doc.Template.Top = topSpace;

2). Draw PDF header, including header label font, alignment and location.

[C#]
            PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Calibri", 10f, FontStyle.Regular));
            PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Right);
            String label = "Demo of Spire.Pdf";
            SizeF size = font.MeasureString(label, format);
            float y = topSpace.Height - font.Height - 1;
            PdfPen pen = new PdfPen(Color.SlateGray, 0.75f);
            topSpace.Graphics.SetTransparency(0.5f);
            topSpace.Graphics.DrawLine(pen, margin.Left, y, pageSize.Width - margin.Right, y);
            y = y - 1 - size.Height;
            topSpace.Graphics.DrawString(label, font, PdfBrushes.SlateGray, pageSize.Width - margin.Right, y, format);

Header Image:

Create FormField

3). Set template right space and bottom space.

[C#]
            PdfPageTemplateElement rightSpace
                = new PdfPageTemplateElement(margin.Right, pageSize.Height);
            doc.Template.Right = rightSpace;

            PdfPageTemplateElement bottomSpace
                = new PdfPageTemplateElement(pageSize.Width, margin.Bottom);
            bottomSpace.Foreground = true;
            doc.Template.Bottom = bottomSpace;

4). Draw PDF footer

Besides set footer label font, alignment and location, set label text format as page {0} of {1} to show page number.
[C#]
            y = font.Height + 1;
            bottomSpace.Graphics.SetTransparency(0.5f);
            bottomSpace.Graphics.DrawLine(pen, margin.Left, y, pageSize.Width - margin.Right, y);
            y = y + 1;
            PdfPageNumberField pageNumber = new PdfPageNumberField();
            PdfPageCountField pageCount = new PdfPageCountField();
            PdfCompositeField pageNumberLabel = new PdfCompositeField();
            pageNumberLabel.AutomaticFields
                = new PdfAutomaticField[] { pageNumber, pageCount };
            pageNumberLabel.Brush = PdfBrushes.SlateGray;
            pageNumberLabel.Font = font;
            pageNumberLabel.StringFormat = format;
            pageNumberLabel.Text = "page {0} of {1}";
            pageNumberLabel.Draw(bottomSpace.Graphics, pageSize.Width - margin.Right, y);

Footer Image:

Create FormField

Step 3: Create page and draw page title

[C#]
            PdfPageBase page = doc.Pages.Add(PdfPageSize.A4, new PdfMargins(0));
            float y = 20;
            y = DrawPageTitle(page, y);

Details of DrawPageTitle Method:

1). Add title text and set font, color and location for it.

[C#]
            PdfBrush brush1 = PdfBrushes.DarkCyan;
            PdfBrush brush2 = PdfBrushes.Red;
            PdfTrueTypeFont font1 = new PdfTrueTypeFont(new Font("Calibri", 12f, FontStyle.Bold));
            String title = "Your Account Information(* Required)";
            SizeF size = font1.MeasureString(title);
            float x = (page.Canvas.ClientSize.Width - size.Width) / 2;
            page.Canvas.DrawString("Your Account Information(", font1, brush1, x, y);
            size = font1.MeasureString("Your Account Information(");
            x = x + size.Width;
            page.Canvas.DrawString("* Required", font1, brush2, x, y);
            size = font1.MeasureString("* Required");
            x = x + size.Width;
            page.Canvas.DrawString(")", font1, brush1, x, y);
            y = y + size.Height;

2). Add distance between title and the following sentence

The following sentence shows notes for readers.

[C#]
            y = y + 3;
            PdfTrueTypeFont font2 = new PdfTrueTypeFont(new Font("Calibri", 9f, FontStyle.Italic));
            String p = "Your information is protected and will not be shared with anyone.";
            page.Canvas.DrawString(p, font2, PdfBrushes.Black, 0, y);
            return y + font2.Height;

Step 4: Load form data in xml file

Image Form.xml

Create FormField

1). Put form data from xml in stream

Then, create XPath document to save data in stream and find section nodes according to string “form/section”.
[C#]
            using (Stream stream = File.OpenRead(@"D:\work\My Documents\Form.xml"))
            {
                XPathDocument xpathDoc = new XPathDocument(stream);
                XPathNodeIterator sectionNodes = xpathDoc.CreateNavigator().Select("/form/section");
            }

2). Assign value as 0 for field index

Use foreach sentence to get each section and each field in document. Draw section and field in PDF as structure in xml file.

[C#]
                int fieldIndex = 0;
                foreach (XPathNavigator sectionNode in sectionNodes)
                {
                    //Draw Section Label
                    String sectionLabel = sectionNode.GetAttribute("name", "");
                    y = DrawFormSection(sectionLabel, page, y);

                    XPathNodeIterator fieldNodes = sectionNode.Select("field");
                    foreach (XPathNavigator fieldNode in fieldNodes)
                    {
                        y = DrawFormField(fieldNode, doc.Form, page, y, fieldIndex++);
                    }
                }

Details of DrawFormSection Method:

Include section background color, font type, font color and section rectangle.

[C#]
        static float DrawFormSection(String label, PdfPageBase page, float y)
        {
            PdfBrush brush1 = PdfBrushes.GhostWhite;
            PdfBrush brush2 = PdfBrushes.DeepSkyBlue;
            PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Calibri", 11f, FontStyle.Bold));
            PdfStringFormat format = new PdfStringFormat();
            float height = font.MeasureString(label).Height;
            page.Canvas.DrawRectangle(brush2, 0, y, page.Canvas.ClientSize.Width, height + 2);
            page.Canvas.DrawString(label, font, brush1, 2, y + 1);
            y = y + height + 2;
            PdfPen pen = new PdfPen(PdfBrushes.DeepSkyBlue, 0.25f);
            page.Canvas.DrawLine(pen, 0, y, page.Canvas.ClientSize.Width, y);
            return y + 0.75f;
        }

Details of DrawFormField Method:

a. Measure field label. Get label attribute value from nodes. Then, set label format and size

[C#]
        static float DrawFormField(XPathNavigator fieldNode, PdfForm form, PdfPageBase page, float y, int fieldIndex)
        {
            float width = page.Canvas.ClientSize.Width;
            float padding = 2;
            String label = fieldNode.GetAttribute("label", "");
            PdfTrueTypeFont font1 = new PdfTrueTypeFont(new Font("Calibri", 10f));
            PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Right, PdfVerticalAlignment.Middle);
            float labelMaxWidth = width * 0.4f - 2 * padding;
            SizeF labelSize = font1.MeasureString(label, labelMaxWidth, format);
        }

b. Measure field height

[C#]
            float fieldHeight = MeasureFieldHeight(fieldNode);
            float height = labelSize.Height > fieldHeight ? labelSize.Height : fieldHeight;
            height = height + 2;

c. Draw background and field label

[C#]
            PdfBrush brush = PdfBrushes.GhostWhite;
            page.Canvas.DrawRectangle(brush, 0, y, width, height);
            PdfBrush brush1 = PdfBrushes.DarkCyan;
            RectangleF labelBounds = new RectangleF(padding, y, labelMaxWidth, height);
            page.Canvas.DrawString(label, font1, brush1, labelBounds, format);

d. Draw field

Firstly, set field max width and location. Secondly, get values of field type, ID and required fields. Thirdly, use switch sentence to judge field type and draw different fields according to judgment.

[C#]
            float fieldMaxWidth = width * 0.57f - 2 * padding;
            float fieldX = labelBounds.Right + 2 * padding;
            float fieldY = y + (height - fieldHeight) / 2;
            String fieldType = fieldNode.GetAttribute("type", "");
            String fieldId = fieldNode.GetAttribute("id", "");
            bool required = "true" == fieldNode.GetAttribute("required", "");
            switch (fieldType)
            {
                case "text":
                case "password":
                    PdfTextBoxField textField = new PdfTextBoxField(page, fieldId);
                    textField.Bounds = new RectangleF(fieldX, fieldY, fieldMaxWidth, fieldHeight);
                    textField.BorderWidth = 0.25f;
                    textField.BorderStyle = PdfBorderStyle.Solid;
                    textField.Required = required;
                    if ("password" == fieldType)
                    {
                        textField.Password = true;
                    }
                    if ("true" == fieldNode.GetAttribute("multiple", ""))
                    {
                        textField.Multiline = true;
                        textField.Scrollable = true;
                    }
                    form.Fields.Add(textField);
                    break;
                case "checkbox":
                    PdfCheckBoxField checkboxField = new PdfCheckBoxField(page, fieldId);
                    float checkboxWidth = fieldHeight - 2 * padding;
                    float checkboxHeight = checkboxWidth;
                    checkboxField.Bounds = new RectangleF(fieldX, fieldY + padding, checkboxWidth, checkboxHeight);
                    checkboxField.BorderWidth = 0.25f;
                    checkboxField.Style = PdfCheckBoxStyle.Cross;
                    checkboxField.Required = required;
                    form.Fields.Add(checkboxField);
                    break;

                case "list":
                    XPathNodeIterator itemNodes = fieldNode.Select("item");
                    if ("true" == fieldNode.GetAttribute("multiple", ""))
                    {
                        PdfListBoxField listBoxField = new PdfListBoxField(page, fieldId);
                        listBoxField.Bounds = new RectangleF(fieldX, fieldY, fieldMaxWidth, fieldHeight);
                        listBoxField.BorderWidth = 0.25f;
                        listBoxField.MultiSelect = true;
                        listBoxField.Font = new PdfFont(PdfFontFamily.Helvetica, 9f);
                        listBoxField.Required = required;
                        //add items into list box.
                        foreach (XPathNavigator itemNode in itemNodes)
                        {
                            String text = itemNode.SelectSingleNode("text()").Value;
                            listBoxField.Items.Add(new PdfListFieldItem(text, text));
                        }
                        listBoxField.SelectedIndex = 0;
                        form.Fields.Add(listBoxField);

                        break;
                    }
                    if (itemNodes != null && itemNodes.Count <= 3)
                    {
                        PdfRadioButtonListField radioButtonListFile
                            = new PdfRadioButtonListField(page, fieldId);
                        radioButtonListFile.Required = required;
                        //add items into radio button list.
                        float fieldItemHeight = fieldHeight / itemNodes.Count;
                        float radioButtonWidth = fieldItemHeight - 2 * padding;
                        float radioButtonHeight = radioButtonWidth;
                        foreach (XPathNavigator itemNode in itemNodes)
                        {
                            String text = itemNode.SelectSingleNode("text()").Value;
                            PdfRadioButtonListItem fieldItem = new PdfRadioButtonListItem(text);
                            fieldItem.BorderWidth = 0.25f;
                            fieldItem.Bounds = new RectangleF(fieldX, fieldY + padding, radioButtonWidth, radioButtonHeight);
                            radioButtonListFile.Items.Add(fieldItem);

                            float fieldItemLabelX = fieldX + radioButtonWidth + padding;
                            SizeF fieldItemLabelSize = font1.MeasureString(text);
                            float fieldItemLabelY = fieldY + (fieldItemHeight - fieldItemLabelSize.Height) / 2;
                            page.Canvas.DrawString(text, font1, brush1, fieldItemLabelX, fieldItemLabelY);

                            fieldY = fieldY + fieldItemHeight;
                        }
                        form.Fields.Add(radioButtonListFile);

                        break;
                    }

                    //combo box
                    PdfComboBoxField comboBoxField = new PdfComboBoxField(page, fieldId);
                    comboBoxField.Bounds = new RectangleF(fieldX, fieldY, fieldMaxWidth, fieldHeight);
                    comboBoxField.BorderWidth = 0.25f;
                    comboBoxField.Font = new PdfFont(PdfFontFamily.Helvetica, 9f);
                    comboBoxField.Required = required;
                    //add items into combo box.
                    foreach (XPathNavigator itemNode in itemNodes)
                    {
                        String text = itemNode.SelectSingleNode("text()").Value;
                        comboBoxField.Items.Add(new PdfListFieldItem(text, text));
                    }
                    form.Fields.Add(comboBoxField);
                    break;
            }

e. Draw * for required fields

[C#]
            if (required)
            {
                //draw *
                float flagX = width * 0.97f + padding;
                PdfTrueTypeFont font3 = new PdfTrueTypeFont(new Font("Calibri", 10f, FontStyle.Bold));
                SizeF size = font3.MeasureString("*");
                float flagY = y + (height - size.Height) / 2;
                page.Canvas.DrawString("*", font3, PdfBrushes.Red, flagX, flagY);
            }

Details of MeasureFieldHeight Method:

Get field type and set default height. Use switch sentence to judge field type. If field types are password, check box and list, set different height for them. If not, throw an error message.

[C#]
        static float MeasureFieldHeight(XPathNavigator fieldNode)
        {
            String fieldType = fieldNode.GetAttribute("type", "");
            float defaultHeight = 16f;
            switch (fieldType)
            {
                case "text":
                case "password":
                    if ("true" == fieldNode.GetAttribute("multiple", ""))
                    {
                        return defaultHeight * 3;
                    }
                    return defaultHeight;

                case "checkbox":
                    return defaultHeight;

                case "list":
                    if ("true" == fieldNode.GetAttribute("multiple", ""))
                    {
                        return defaultHeight * 3;
                    }
                    XPathNodeIterator itemNodes = fieldNode.Select("item");
                    if (itemNodes != null && itemNodes.Count <= 3)
                    {
                        return defaultHeight * 3;
                    }
                    return defaultHeight;
            }
            String message = String.Format("Invalid field type: {0}", fieldType);
            throw new ArgumentException(message);
         }

Step 5: Draw submit button to submit form to server or website

[C#]
            y = y + 20;
            float buttonWidth = 80;
            float buttonX = (page.Canvas.ClientSize.Width - buttonWidth) / 2;
            RectangleF buttonBounds = new RectangleF(buttonX, y, buttonWidth, 16f);
            PdfButtonField button = new PdfButtonField(page, "submit");
            button.Text = "Submit";
            button.Bounds = buttonBounds;
            button.BorderColor = Color.DarkCyan;
            button.BackColor = Color.GhostWhite;
            PdfSubmitAction submitAction = new PdfSubmitAction("http://www.e-iceblue.com");
            button.Actions.MouseUp = submitAction;
            doc.Form.Fields.Add(button);

Image Submit button:

Create FormField

Step 6: Save and launch file

[C#]
            doc.SaveToFile("FormField.pdf");
            doc.Close();
            System.Diagnostics.Process.Start("FormField.pdf");

Effective Screenshot:

Create FormField

Spire.PDF is a PDF document creation component that enables your .NET/Silverlight applications to read, write and manipulate PDF documents without using Adobe Acrobat. Now, the new version added Silverlight platform which makes it more powerful.