Search code examples
c#pdfitextfieldunderline

Underline form field value using itextsharp


I have an application that uses itextsharp to fill PDF form fields.

I got new requirement from the customer to allow underlining the fields values.

I have read many posts including answers to questions in this site but I could't figure out a way to do it.

Current my code does the following:

  1. Creates a PDFStamper instance
  2. Get the form fields using stamper.AcroFields property
  3. Set the field value using the AcroFields.SetFieldRichValue() method.

But when I am opening the PDF the field is empty.

I verified that the field is set as rich text in the PDF itself.

Any idea what I am doing wrong ?

Here is a snnipest of my code:

                FileStream stream = File.Open(targetFile, FileMode.Create);                                     
                var pdfStamper = new PdfStamper(new PdfReader(sourceFile), stream);                     

                // Iterate the fields in the PDF
                foreach (var fieldName in pdfStamper.AcroFields.Fields.Keys)
                {                       
                    // Get the field value of the current field
                    var fieldValue = "<?xml version=\"1.0\"?><body xmlns=\"http://www.w3.org/1999/xtml\" xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\" xfa:contentType=\"text/html\" xfa:APIVersion=\"Acrobat:8.0.0\" xfa:spec=\"2.4\"><p style=\"text-align:left\"><b><i>Here is some bold italic text</i></b></p><p style= \"font-size:16pt\">This text uses default text state parameters but changes the font size to 16.</p></body>"

                    // Set the field value
                    if (String.IsNullOrEmpty(fieldValue) == false)
                    {
                        pdfStamper.AcroFields.SetFieldRichValue(key, fieldValue);
                    }
                }

Edit:

I have revised my code based on Mark Storer's post to a question (http://stackoverflow.com/questions/1454701/adding-rich-text-to-an-acrofield-in-itextsharp). The new code is:

        // Create reader to read the source file
        var reader = new PdfReader(sourceFile);

        // Create a stream for the generated file
        var stream = File.Open(targetFile, FileMode.Create); 

        // Create stamper to generate the new file
        var pdfStamper = new PdfStamper(reader, stream);

        // Field name and value
        var fieldName = "myfield";
        var fieldValue = "<?xml version=\"1.0\"?><body xfa:APIVersion=\"Acroform:2.7.0.0\" xfa:spec=\"2.1\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\"><p dir=\"ltr\" style=\"margin-top:0pt;margin-bottom:0pt;font-family:Helvetica;font-size:12pt\"><b>write line1 bold</b></p</body>";

        // Output stream for the temporary file that should contain the apearance of the field
        var msOutput = new FileStream(@"d:\temp.pdf", FileMode.Create);

        // string reader to read the field value
        var textReader = new StringReader(fieldValue);

        // Create new document
        var document = new Document(pdfStamper.AcroFields.GetFieldPositions(fieldName)[0].position);

         // writer for the new doucment
        var writer = PdfWriter.GetInstance(document, msOutput);

        // Open the document                
        document.Open();

        // Get elements to append to the doucment
        var list = HTMLWorker.ParseToList(textReader, null);

        // Append elements to the doucment
        foreach (var element in list)
        {
            document.Add(element);
        }                                           

        // close the documnet
        document.Close();                            

        // Append push button that contains the generated content as its apearance
        // this approach is based on the suggestion from Mark storer that can be found in:
        // http://stackoverflow.com/questions/1454701/adding-rich-text-to-an-acrofield-in-itextsharp
        var button = new PushbuttonField(pdfStamper.Writer, pdfStamper.AcroFields.GetFieldPositions(fieldName)[0].position, fieldName + "_")
                             {
                                 Layout = PushbuttonField.LAYOUT_ICON_ONLY,
                                 BackgroundColor = null,
                                 Template = pdfStamper.Writer.GetImportedPage(new PdfReader(targetFile, 1)
                             };
            pdfStamper.AddAnnotation(button.Field, 1);                

        pdfStamper.FormFlattening = true;
        pdfStamper.Close();
        pdfStamper.Dispose();

But the problem now is that the temporary document contains no content....

Any ideas ?


Solution

  • I managed to resolve it with little trick - I used Anchor (hyperling) element inside ColumnText element and position it above the form field. The anchor is displayed with underline by default. In order to avoid the hand marker when the user hover the mouse on the anchor, I set the "Reference" property of the anchor to null.

    Here is the code I used:

     // Create reader
     var reader = new PdfReader(sourceFilePathAndName);
    
     // Create stream for the target file
     var stream = File.Open(targetFilePathAndName, FileMode.Create); 
    
     // Create the stamper
     var pdfStamper = new PdfStamper(reader, stream);
    
     const string fieldName = "MyField";     
    
     // Get the position of the field
     var targetPosition = pdfStamper.AcroFields.GetFieldPositions(fieldName)[0].position;
    
     // Set the font
     var fontNormal = FontFactory.GetFont("Arial", 16, Font.UNDERLINE, BaseColor.BLACK);
    
     // Create the anchor
     var url = new Anchor("some default text", fontNormal) { Reference = null };
    
     // Create the element that will contain the anchor and allow to position it anywhere on the document
     var data = new ColumnText(pdfStamper.GetOverContent(1));
    
     // Add the anchor to its container
     data.SetSimpleColumn(url, targetPosition.Left, targetPosition.Bottom, targetPosition.Right, targetPosition.Top, 0, 0);
    
     // Write the content to the document
     data.Go();
    
     pdfStamper.FormFlattening = true;
     pdfStamper.Close();
     pdfStamper.Dispose();