Question

I've been wracking my brain for a couple of days and I am unable to get this working. I am trying to use itextsharp in vb.net and MVC to format a field with bold or underline and then see those changes in the resulting PDF. I am not getting errors but nothing I do changes the fields. The PDF loads fine but the formatting of the fields never changes.

I am trying to convert the text into a pdf paragraph, then loop through its chunks and apply formatting. Then I would like to use "SetField" to fill the field with the resulting string. Something like:

stamper.AcroFields.SetField(fieldName, formattedString)

I am new to this so I am not sure where to troubleshoot further. I have also tried creating a new font and adding that and the document remains unchanged.

I can't upload the PDF file for inspection, but if there is something I should check in the PDF file that might cause this please let me know. The file is in XFA format.

I have the pseudo-code below:

  1. The code that calls the GenerateDocument function:

    Dim pdf As Byte()
    pdf = GenerateDocument()
    Return File(pdf, "application/pdf")
    
  2. The GenerateDocument function(simplified):

    Public Function GenerateDocument() As Byte()
     Using inStream As New MemoryStream(TemplateBinary) 'the actual pdf binary
      Using outStream As New MemoryStream
    
       Dim pdfReader As New text.pdf.PdfReader(inStream)
       Dim stamper As New PdfStamper(pdfReader, outStream)
       Dim form As AcroFields = stamper.AcroFields
       Dim fieldKeys = form.Fields.Keys
    
       stamper.AddViewerPreference(PdfName.HIDETOOLBAR, New PdfBoolean(True))
       stamper.AddViewerPreference(PdfName.FITWINDOW, New PdfBoolean(True))
       stamper.FormFlattening = False
    
       Dim pdfSegment As Paragraph = CreateSimpleHtmlParagraph("sample text")
       Dim pdfString As New StringBuilder
    
       If pdfSegment.Count > 0 Then
         For counter As Integer = 0 To pdfSegment.Count - 1
    
          Dim para As Paragraph
    
          If pdfSegment(counter).GetType().Name().ToUpper().Contains("PARAGRAPH") Then
            para = pdfSegment(counter)
            For Each ch As Chunk In para
             ch.SetUnderline(0.5F, -1.5F) 'just make everything underline for now
            Next
            pdfString.Append(para.Content)
          End If
    
          If counter < (pdfSegment.Count - 1) Then
           pdfString.AppendLine()
          End If
         Next
    
         form.SetField(xNode.Name, pdfString.ToString())
      End If
      stamper.Close()
      pdfReader.Close()
      Return outStream.ToArray()
    
     End Using
     End Using
    End Function
    
  3. The code that makes a PDF paragraph called from the code above

    Private Function CreateSimpleHtmlParagraph(text As String) As Paragraph
    Dim pdfTextSection As New Paragraph()
    
    Using sr As StringReader = New StringReader(text)
    Dim elements As List(Of IElement) = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, Nothing)
    
    For Each e As IElement In elements
     pdfTextSection.Add(e)
    Next
    End Using
    
    Return pdfTextSection
    

    End Function

Was it helpful?

Solution

The code listed under 2 is very strange. You create a Paragraph object which consists of some plain text, a font, leading info, indentation info, etc... Then you ask the Paragraph for the plain text without the font info. Elementary logic tells you that the general StringBuilder class is unaware of iTextSharp-specific concepts such as Chunk, Font and underline.

You are also assuming that an ordinary text field is capable of containing rich text. Ordinary text fields are usually defined to contain text in one single font. For instance: "Helvetica" for regular text. Or "Helvetica Bold" for bold text. "Helvetica" and "Helvetica Bold" are two different fonts (of the same family). It is important not to confuse the concept font with the concept font family.

"Underline" is not a quality of the font. Ordinary text fields can't be defined as "the value needs to be underlined".

This means that you'll need a work-around to achieve what you need. This workaround is described in my book, more specifically where I explain the MovieAds example (look here if you need the C# version).

In this example, I don't use the setField() method because of the limitations of ordinary text fields. Instead, I get the position of the field and I add the rich text using the ColumnText object:

AcroFields.FieldPosition f = form.GetFieldPositions(fieldname)[0];
ColumnText ct = new ColumnText(canvas);
ct.SetSimpleColumn(
  f.position.Left, f.position.GetBottom(2),
  f.position.GetRight(2), f.position.Top
);
ct.AddElement(para);
ct.Go();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top