-1

I’m getting unwanted results in Adobe Reader DC when generating or regenerating a multi-selection list box with iTextSharp in an Acroform PDF document.

Problem: The PDF form is missing deselected display items at the beginning of the list box when viewing the modified PDF in Adobe Reader DC. For example: “One“,“Two“,“Three“,“Four“,“Five“ are list items; and “Two“ and “Four“ are selected; then the previous items such as “One” are missing the top of the list box. And the first item displayed in the list box starts with the first selection, in this case “Two”. (See Adobe Reader DC Screenshot)

FYI: Using Adobe Reader DC, when I select different field selections in the list box, and then click outside the list box, the list box field reverts back to normal appearance with all the items shown. I can’t reproduce this behavior when opening the modified PDF in Adobe Acrobat Professional 8 and all the field items are visible and correctly selected. This missing list items behavior can also be reproduced in GhostScript when converting PDF to BMP or PNG.

Please answer my question: Can you please provide me with a resolution to this issue if this is an iTextSharp problem or if my syntax is incorrect. Would you also please let me know if this behavior can reproduced using your Adobe Reader DC?

Thank you for your support!

Modified Acroform PDF Document with issue: http://www.nk-inc.com/listbox-error.pdf

Adobe Reader DC Screenshot:
(source: nk-inc.com)

ADDITIONAL INFORMATION:
iTextSharp.dll Version: 5.5.6.0
Adobe Reader DC Version: 2015.008.20082
Adobe Acrobat Pro Version: 8.x
Form Type: Acroform PDF

VB.NET CODE (v3.5 – Windows Application):

Imports iTextSharp.text.pdf
Imports iTextSharp.text
Imports System.IO
Public Class listboxTest
    Private Sub RunTest()
        Dim cList As New listboxTest()
        Dim fn As String = Application.StartupPath.ToString.TrimEnd("\") & "\listbox-error.pdf"
        Dim b() As Byte = cList.addListBox(System.IO.File.ReadAllBytes(fn), New iTextSharp.text.Rectangle(231.67, 108.0, 395.67, 197.0), "ListBox1", "ListBox1", 1)
        File.WriteAllBytes(fn, b)
        Process.Start(fn)
    End Sub
    Public Function addListBox(ByVal pdfBytes() As Byte, ByVal newRect As Rectangle, ByVal newFldName As String, ByVal oldfldname As String, ByVal pg As Integer) As Byte()
        Dim pdfReaderDoc As New PdfReader(pdfBytes)
        Dim m As New System.IO.MemoryStream
        Dim b() As Byte = Nothing
        Try
            With New PdfStamper(pdfReaderDoc, m)
                Dim txtField As iTextSharp.text.pdf.TextField
                txtField = New iTextSharp.text.pdf.TextField(.Writer, newRect, newFldName)
                txtField.TextColor = BaseColor.BLACK
                txtField.BackgroundColor = BaseColor.WHITE
                txtField.BorderColor = BaseColor.BLACK
                txtField.FieldName = newFldName 'ListBox1
                txtField.Alignment = 0 'LEFT
                txtField.BorderStyle = 0 'SOLID
                txtField.BorderWidth = 1.0F 'THIN
                txtField.Visibility = TextField.VISIBLE
                txtField.Rotation = 0 'None
                txtField.Box = newRect '231.67, 108.0, 395.67, 197.0
                Dim opt As New PdfArray
                Dim ListBox_ItemDisplay As New List(Of String)
                ListBox_ItemDisplay.Add("One")
                ListBox_ItemDisplay.Add("Two")
                ListBox_ItemDisplay.Add("Three")
                ListBox_ItemDisplay.Add("Four")
                ListBox_ItemDisplay.Add("Five")
                Dim ListBox_ItemValue As New List(Of String)
                ListBox_ItemValue.Add("1X")
                ListBox_ItemValue.Add("2X")
                ListBox_ItemValue.Add("3X")
                ListBox_ItemValue.Add("4X")
                ListBox_ItemValue.Add("5X")
                txtField.Options += iTextSharp.text.pdf.TextField.MULTISELECT
                Dim selIndex As New List(Of Integer)
                Dim selValues As New List(Of String)
                selIndex.Add(CInt(1)) ' SELECT #1 (index)
                selIndex.Add(CInt(3)) ' SELECT #3 (index)
                txtField.Choices = ListBox_ItemDisplay.ToArray
                txtField.ChoiceExports = ListBox_ItemValue.ToArray
                txtField.ChoiceSelections = selIndex
                Dim listField As PdfFormField = txtField.GetListField
                If Not String.IsNullOrEmpty(oldfldname & "") Then
                    .AcroFields.RemoveField(oldfldname, pg)
                End If
                .AddAnnotation(listField, pg)
                .Writer.CloseStream = False
                .Close()
                If m.CanSeek Then
                    m.Position = 0
                End If
                b = m.ToArray
                m.Close()
                m.Dispose()
                pdfReaderDoc.Close()
            End With
            Return b.ToArray
        Catch ex As Exception
            Err.Clear()
        Finally
            b = Nothing
        End Try
        Return Nothing
    End Function
End Class
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Nick K.
  • 1
  • 2

1 Answers1

0

The reason why the visible list starts with the second entry is that iTextSharp starts drawing the list at the first selected entry.

This is an optimization for lists which have more (probably many more) entries than can be displayed in the fixed text box area, so that the displayed entries contain at least one interesting, i.e. selected, one.

Unfortunately this optimization does not consider whether this means leaving some lines empty at the bottom, and in case of lists which fit completely into the text box, there even aren't scroll bars or anything.


But iTextSharp also offers a way to disable this optimization: You can explicitly set the first visible item manually:

txtField.ChoiceSelections = selIndex
txtField.VisibleTopChoice = 0 ' Top visible choice is start of list!
Dim listField As PdfFormField = txtField.GetListField

Adding this middle line makes the generated appearance start at the first list value.

mkl
  • 90,588
  • 15
  • 125
  • 265