Fill in PDF Form Fields using the Open Source iTextSharp Dynamic Link Library(转载)

本文介绍如何使用iTextSharp库自动填充PDF表单。通过示例展示了如何读取PDF中的字段并设置值,适用于没有Adobe专业工具的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

This article describes a quick and simple approach to programmatically completing a PDF document through the use of the iTextSharp DLL. The article also discusses how one might go about using the iTextSharp DLL to discover and map the fields available within an existing PDF if the programmer has only the PDF but, does not have Adobe Designer or even a list of the names of the fields present in the PDF.

screenShotSmall.JPG

Figure 1: Resulting PDF after Filling in Fields Programmatically

iTextSharp is a C# port of a Java library written to support the creation and manipulation of PDF documents. The project is available for download through SourceForge.net. With the iTextSharp DLL, it is possible to not only populate fields in an existing PDF document, but also to dynamically create PDFs. The examples here are limited to a description of the procedures associated with the completion of a PDF. The download will contain examples of PDF creation in both Visual Basic and C#.

The examples contained herein are dependent upon the availability of the iTextSharp DLL. Use the link provided previously in order to download the DLL locally to your development machine. In order to demonstrate filling out a PDF using the iTextSharp DLL, I downloaded a copy of the W-4 PDF form from the IRS website. The form contains controls and may be filled out programmatically so it serves as a good example.

PDF documents that do not contain controls, i.e. those meant to be printed and filled in with a pencil, cannot be completed using this approach. Of course, if you have access to Adobe tools (Adobe Professional, Adobe Designer), you can always create your own PDFs with controls or can add controls to existing PDFs. Further, although not demonstrated here, you can also use iTextSharp to create a PDF document with embedded controls.

Getting Started

In order to get started, fire up the Visual Studio 2005 IDE and open the attached solution. The solution consists of a single Windows Forms project with a single form. I have also included a PDF that will be used for demonstration purposes; this form is the IRS W-4 form completed by US taxpayers. However, any PDF with embedded controls (text boxes, check boxes, etc.) is fair game for this approach. Note that a reference to the iTextSharp DLL has been included in the project.

All of the project code is contained within the single Windows Form. The form itself contains only a docked textbox used to display all of the field names from an existing PDF document. The completed PDF is generated and stored in the local file system; the PDF is not opened for display by the application.

The application uses the existing PDF as a template and from that template, it creates and populates the new PDF. The template PDF itself is never populated and it is used only to define the format and contents of the completed PDF.

f2.jpg

Figure 2: Solution Explorer

The Code: Main Form

As was previously mentioned, all of the code used in the demonstration application is contained entirely in the project’s single Windows Form. The following section will describe the contents of the code file.

The file begins with the appropriate library imports needed to support the code. Note that the iTextSharp libraries have been included into the project. The namespace and class declaration are in the default configuration.

Collapse Copy Code
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using System.IO;

namespace PdfGenerator
{
    public partial class Form1 : Form
    {

The next section of code contains the default constructor and the Form1 load event handler. During form load, two functions are called. Those functions are used to display all of the fields present in the template PDF and to create a new PDF populated with a set of field values.

Collapse Copy Code
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            ListFieldNames();
            FillForm();
        }

The next section of code contained in the demo application defines a function used to collect the names of all of the fields from the target PDF. The field names are displayed in a text box contained in the application’s form.

Collapse Copy Code
        /// <summary>
        /// List all of the form fields into a textbox. The
        /// form fields identified can be used to map each of the
        /// fields in a PDF.
        /// </summary>
        private void ListFieldNames()
        {
            string pdfTemplate = @"c:\Temp\PDF\fw4.pdf";
            // title the form

            this.Text += " - " + pdfTemplate;
            // create a new PDF reader based on the PDF template document

            PdfReader pdfReader = new PdfReader(pdfTemplate);
            // create and populate a string builder with each of the 
            // field names available in the subject PDF

            StringBuilder sb = new StringBuilder();
            foreach (DictionaryEntry de in pdfReader.AcroFields.Fields)
            {
                sb.Append(de.Key.ToString() + Environment.NewLine);
            }
            // Write the string builder's content to the form's textbox

            textBox1.Text = sb.ToString();
            textBox1.SelectionStart = 0;
        }

Figure 3 shows the field names collected from the target PDF using the ListFieldNames function call. In order to map these fields to specific fields in the PDF, one need only copy this list and pass values to each of the fields to identify them. For example, if the form contains ten fields, setting the value (shown next) to a sequential number will result in the display of the numbers 1 to 10 in each of the fields. One can then track that field value back to the field name using this list as the basis for the map. Once the fields have been identified, the application can be written to pass the correct values to the related field.

Checkbox controls may be a little more challenging to figure out. I tried passing several values to the checkbox controls before lining up a winner. In this example, I tried pass 0, 1, true, false, etc. to the field before figuring out that yes sets the check.

f3.jpg

Figure 3: The Available PDF Fields

The next section of code in the demo project is used to fill in the mapped field values. The process is simple enough. The first thing that happens is that that the template file and new file locations are defined and passed to string variables. Once the paths are defined, the code creates an instance of the PDF reader which is used to read the template file, and a PDF stamper which is used to fill in the form fields in the new file. Once the template and target files are set up, the last thing to do is create an instance of AcroFields, which is populated with all of the fields contained in the target PDF. After the form fields have been captured, the rest of the code is used to fill in each field using the field’s SetField function.

In this example, the first worksheet and the W-4 itself are populated with meaningful values whilst the second worksheet is populated with sequential numbers that are then used to map those fields to their location on the PDF. After the PDF has been filled out, the application reads values from the PDF (the first and last names) in order to generate a message indicating that the W-4 for this person was completed and stored.

Collapse Copy Code
        private void FillForm()
        {
            string pdfTemplate = @"c:\Temp\PDF\fw4.pdf";
            string newFile = @"c:\Temp\PDF\completed_fw4.pdf";
            PdfReader pdfReader = new PdfReader(pdfTemplate);
            PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(
                newFile, FileMode.Create));
            AcroFields pdfFormFields = pdfStamper.AcroFields;
            // set form pdfFormFields
            // The first worksheet and W-4 form

            pdfFormFields.SetField("f1_01(0)", "1"); 
            pdfFormFields.SetField("f1_02(0)", "1");
            pdfFormFields.SetField("f1_03(0)", "1");
            pdfFormFields.SetField("f1_04(0)", "8");
            pdfFormFields.SetField("f1_05(0)", "0");
            pdfFormFields.SetField("f1_06(0)", "1");
            pdfFormFields.SetField("f1_07(0)", "16");
            pdfFormFields.SetField("f1_08(0)", "28");
            pdfFormFields.SetField("f1_09(0)", "Franklin A.");
            pdfFormFields.SetField("f1_10(0)", "Benefield");
            pdfFormFields.SetField("f1_11(0)", "532");
            pdfFormFields.SetField("f1_12(0)", "12");
            pdfFormFields.SetField("f1_13(0)", "1234");
            // The form's checkboxes
            pdfFormFields.SetField("c1_01(0)", "0");
            pdfFormFields.SetField("c1_02(0)", "Yes");
            pdfFormFields.SetField("c1_03(0)", "0");
            pdfFormFields.SetField("c1_04(0)", "Yes");
            // The rest of the form pdfFormFields
            pdfFormFields.SetField("f1_14(0)", "100 North Cujo Street");
            pdfFormFields.SetField("f1_15(0)", "Nome, AK 67201");
            pdfFormFields.SetField("f1_16(0)", "9");
            pdfFormFields.SetField("f1_17(0)", "10");
            pdfFormFields.SetField("f1_18(0)", "11");
            pdfFormFields.SetField("f1_19(0)", "Walmart, Nome, AK");
            pdfFormFields.SetField("f1_20(0)", "WAL666");
            pdfFormFields.SetField("f1_21(0)", "AB");
            pdfFormFields.SetField("f1_22(0)", "4321");
            // Second Worksheets pdfFormFields
            // In order to map the fields, I just pass them a sequential
            // number to mark them; once I know which field is which, I 
            // can pass the appropriate value
            pdfFormFields.SetField("f2_01(0)", "1");
            pdfFormFields.SetField("f2_02(0)", "2");
            pdfFormFields.SetField("f2_03(0)", "3");
            pdfFormFields.SetField("f2_04(0)", "4");
            pdfFormFields.SetField("f2_05(0)", "5");
            pdfFormFields.SetField("f2_06(0)", "6");
            pdfFormFields.SetField("f2_07(0)", "7");
            pdfFormFields.SetField("f2_08(0)", "8");
            pdfFormFields.SetField("f2_09(0)", "9");
            pdfFormFields.SetField("f2_10(0)", "10");
            pdfFormFields.SetField("f2_11(0)", "11");
            pdfFormFields.SetField("f2_12(0)", "12");
            pdfFormFields.SetField("f2_13(0)", "13");
            pdfFormFields.SetField("f2_14(0)", "14");
            pdfFormFields.SetField("f2_15(0)", "15");
            pdfFormFields.SetField("f2_16(0)", "16");
            pdfFormFields.SetField("f2_17(0)", "17");
            pdfFormFields.SetField("f2_18(0)", "18");
            pdfFormFields.SetField("f2_19(0)", "19");
            // report by reading values from completed PDF
            string sTmp = "W-4 Completed for " + 
                pdfFormFields.GetField("f1_09(0)") + " " +
                pdfFormFields.GetField("f1_10(0)");
            MessageBox.Show(sTmp, "Finished");
            // flatten the form to remove editting options, set it to false
            // to leave the form open to subsequent manual edits
    
            pdfStamper.FormFlattening = false;
            // close the pdf
    
            pdfStamper.Close();
        }
    }
}

To finish up the PDF, it is necessary to determine whether or not additional edits will be permitted to the PDF after it has been programmatically completed. This task is accomplished by setting the FormFlattening value to true or false. If the value is set to false, the resulting PDF will be available for edits, but if the value is set to true, the PDF will be locked against further edits. Once the form has been completed, the PDF stamper is closed and the function terminated.

That wraps up the discussion of the form-based demo project.

Summary

This article described an approach to populating a PDF document with values programmatically. This functionality was accomplished using the iTextSharp DLL. Further, the article described an approach for mapping the fields contained in a PDF and may be useful if one is dealing with a PDF authored elsewhere and if the programmer does not have access to Adobe Professional or Adobe Designer.

The iTextSharp library is a powerful DLL that supports authoring PDFs, as well as using them in the manner described in this document. However, when authoring a PDF, it seems that it would be far easier to produce a nice document using the visual environment made available through the use of Adobe tools. Having said that, if one is dynamically creating PDFs with variable content, the iTextSharp library does provide the tools necessary to support such an effort. With the library, one can create and populate a PDF on the fly.

History

  • 22 January, 2008 -- Original version posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

salysle


Member

Occupation: Software Developer (Senior)
Location: United States United States

 

转载自:http://www.codeproject.com/KB/cs/FillFormFieldsOfPDFs.aspx

转载于:https://www.cnblogs.com/wuhenke/archive/2010/05/11/1733027.html

CH341A编程器是一款广泛应用的通用编程设备,尤其在电子工程和嵌入式系统开发领域中,它被用来烧录各种类型的微控制器、存储器和其他IC芯片。这款编程器的最新版本为1.3,它的一个显著特点是增加了对25Q256等32M芯片的支持。 25Q256是一种串行EEPROM(电可擦可编程只读存储器)芯片,通常用于存储程序代码、配置数据或其他非易失性信息。32M在这里指的是存储容量,即该芯片可以存储32兆位(Mbit)的数据,换算成字节数就是4MB。这种大容量的存储器在许多嵌入式系统中都有应用,例如汽车电子、工业控制、消费电子设备等。 CH341A编程器的1.3版更新,意味着它可以与更多的芯片型号兼容,特别是针对32M容量的芯片进行了优化,提高了编程效率和稳定性。26系列芯片通常指的是Microchip公司的25系列SPI(串行外围接口)EEPROM产品线,这些芯片广泛应用于各种需要小体积、低功耗和非易失性存储的应用场景。 全功能版的CH341A编程器不仅支持25Q256,还支持其他大容量芯片,这意味着它具有广泛的兼容性,能够满足不同项目的需求。这包括但不限于微控制器、EPROM、EEPROM、闪存、逻辑门电路等多种类型芯片的编程。 使用CH341A编程器进行编程操作时,首先需要将设备通过USB连接到计算机,然后安装相应的驱动程序和编程软件。在本例中,压缩包中的"CH341A_1.30"很可能是编程软件的安装程序。安装后,用户可以通过软件界面选择需要编程的芯片类型,加载待烧录的固件或数据,然后执行编程操作。编程过程中需要注意的是,确保正确设置芯片的电压、时钟频率等参数,以防止损坏芯片。 CH341A编程器1.3版是面向电子爱好者和专业工程师的一款实用工具,其强大的兼容性和易用性使其在众多编程器中脱颖而出。对于需要处理25Q256等32M芯片的项目,或者26系列芯片的编程工作,CH341A编程器是理想的选择。通过持续的软件更新和升级,它保持了与现代电子技术同步,确保用户能方便地对各种芯片进行编程和调试。
内存分区情况的分析是嵌入式系统开发中的一个重要环节,特别是在资源有限的MCU(微控制器)环境中。标题提到的工具是一款专为分析Linux环境下的`gcc-map`文件设计的工具,这类文件在编译过程结束后生成,包含了程序在目标设备内存中的布局信息。这个工具可以帮助开发者理解程序在RAM、ROM以及FLASH等存储区域的占用情况,从而进行优化。 `gcc-map`文件通常包含以下关键信息: 1. **符号表**:列出所有定义的全局和静态变量、函数以及其他符号,包括它们的地址和大小。 2. **节区分配**:显示每个代码和数据节区在内存中的位置,比如.text(代码)、.data(已初始化数据)、.bss(未初始化数据)等。 3. **内存汇总**:总览所有节区的大小,有助于评估程序的整体内存需求。 4. **重定位信息**:显示了代码和数据如何在目标地址空间中定位。 该分析工具可能提供以下功能: 1. **可视化展示**:将内存分配以图形化方式呈现,便于直观理解。 2. **详细报告**:生成详细的分析报告,列出每个符号的大小和位置。 3. **比较功能**:对比不同编译版本或配置的`map`文件,查看内存使用的变化。 4. **统计分析**:计算各种内存区域的使用率,帮助识别潜在的优化点。 5. **自定义过滤**:允许用户根据需要筛选和关注特定的符号或节区。 虽然在MCU环境中,Keil IDE自带的工具可能更方便,因为它们通常针对特定的MCU型号进行了优化,提供更加细致的硬件相关分析。然而,对于通用的Linux系统或跨平台项目,这款基于`gcc-map`的分析工具提供了更广泛的适用性。 在实际使用过程中,开发者可以利用这款工具来: - **优化内存使用**:通过分析哪些函数或数据占用过多的内存,进行代码重构或调整链接器脚本以减小体积。 - **排查内存泄漏**:结合其他工具,比如动态内存检测工具,查找可能导致内存泄漏的部分。 - **性能调优**:了解代码执行时的内存分布,有助于提高运行效率。 - **满足资源限制**:在嵌入式系统中,确保程序能在有限的内存空间内运行。 总结来说,`gcc-amap`这样的工具对于深入理解程序的内存布局和资源消耗至关重要,它能帮助开发者做出更明智的决策,优化代码以适应不同的硬件环境。在处理`map`文件时,开发者不仅能获取到程序的内存占用情况,还能进一步挖掘出可能的优化空间,从而提升系统的整体性能和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值