0

I'm trying to add a table to the PDF file I'm generating. I can add stuff "directly" but want to put the various paragraphs or phrases in table cells to get everything to align nicely.

The following code should add three paragraphs "free-form" first, then the same three in a table. However, only the first three display - the table is nowhere to be seen. Here's the code:

try
{
    using (var ms = new MemoryStream())
    {    
        using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))
        {
            using (var writer = PdfWriter.GetInstance(doc, ms))
            {
                doc.Open();

                var titleFont = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.BLACK);
                var docTitle = new Paragraph("UCSC Direct - Direct Payment Form", titleFont);
                doc.Add(docTitle);

                var subtitleFont = FontFactory.GetFont("Times Roman", 9, BaseColor.BLACK);
                var subTitle = new Paragraph("(not to be used for reimbursement of services)", subtitleFont);
                doc.Add(subTitle);

                var importantNoticeFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
                var importantNotice = new Paragraph("Important: Form must be filled out in Adobe Reader or Acrobat Professional 8.1 or above. To save completed forms, Acrobat Professional is required. For technical and accessibility assistance, contact the Campus Controller's Office.", importantNoticeFont);
                importantNotice.Leading = 0;
                importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings
                importantNotice.ExtraParagraphSpace = 4; // ? test this....
                doc.Add(importantNotice);

                // Add a table
                PdfPTable table = new PdfPTable(10); // the arg is the number of columns

                // Row 1
                PdfPCell cell = new PdfPCell(docTitle);
                cell.Colspan = 3;
                cell.BorderWidth = 0;
                //cell.BorderColor = BaseColor.WHITE; <= this works for me, but if background is something other than white, it wouldn't
                cell.HorizontalAlignment = 0; //0=Left, 1=Centre, 2=Right
                table.AddCell(cell);

                // Row 2
                PdfPCell cellCaveat = new PdfPCell(subTitle);
                cellCaveat.Colspan = 2;
                cellCaveat.BorderWidth = 0;
                table.AddCell(cellCaveat);

                // Row 3
                PdfPCell cellImportantNote = new PdfPCell(importantNotice);
                cellImportantNote.Colspan = 5;
                cellImportantNote.BorderWidth = 0;
                table.AddCell(importantNotice);

                doc.Add(table);

                doc.Close();
            }
            var bytes = ms.ToArray();
            String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
            PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
            var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
            File.WriteAllBytes(testFile, bytes);
            MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
        }
    }
}
catch (DocumentException dex)
{
    throw (dex);
}
catch (IOException ioex)
{
    throw (ioex);
}
catch (Exception ex)
{
    String exMsg = ex.Message;
    MessageBox.Show(String.Format("Boo-boo!: {0}", ex.Message));
}

Why is my borderless table invisible or nonexistant?

UPDATE

Based on Bruno's answer, and applying it to the output that I really need, this works:

using (var ms = new MemoryStream())
{
    using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))                     {
        //Create a writer that's bound to our PDF abstraction and our stream
        using (var writer = PdfWriter.GetInstance(doc, ms))
        {

            //Open the document for writing
            doc.Open();

            // Mimic the appearance of Direct_Payment.pdf
            var courierBold11Font = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.BLACK);
            var docTitle = new Paragraph("UCSC - Direct Payment Form", courierBold11Font);
            doc.Add(docTitle);

            var timesRoman9Font = FontFactory.GetFont("Times Roman", 9, BaseColor.BLACK);
            var subTitle = new Paragraph("(not to be used for reimbursement of services)", timesRoman9Font);
            doc.Add(subTitle);

            var courier9RedFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
            var importantNotice = new Paragraph("Important: Form must be filled out in Adobe Reader or Acrobat Professional 8.1 or above. To save completed forms, Acrobat Professional is required. For technical and accessibility assistance, contact the Campus Controller's Office.", courier9RedFont);
            importantNotice.Leading = 0;
            importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings

            // Add a table
            PdfPTable table = new PdfPTable(1);
            PdfPCell cellImportantNote = new PdfPCell(importantNotice);
            cellImportantNote.BorderWidth = PdfPCell.NO_BORDER;
            table.WidthPercentage = 50;
            table.HorizontalAlignment = Element.ALIGN_LEFT;
            table.AddCell(cellImportantNote);
            doc.Add(table);

            doc.Close();
        }
        var bytes = ms.ToArray();
        String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
        PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
        var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
        File.WriteAllBytes(testFile, bytes);
        MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
    }
}
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Which version of iTextSharp are you using? Why does your comments mention different rows, when in fact you're adding everything to a single row? Why are you using colspan to mimic column width? But most importantly: which documentation did you read? Because it seems that the tutorials you've been following (if any) are really bad. Is there a specific reason why you're not using the official documentation? – Bruno Lowagie Apr 10 '15 at 07:18
  • I'm using version 5.5.5.0. As to mentioning different rows, that's what I want to do - but don't know how. It seems to me there should be a way, when using a table, to specify the precise cell (col num, row num) into which you want to place content). I exepct colspan to be similar to XAML, where you can spread content over several columns. Which documentation: various things I find via google/bing searches. Most of the "official" docs seem to be about iText, not iTextSharp. – B. Clay Shannon-B. Crow Raven Apr 13 '15 at 15:20
  • 1
    Colspan *does* allow you to spread content over several columns, but your Math is all wrong. As for the documentation, I've had this discussion before: you should read the iText code as if it were pseudo code. Converting iText code to iTextSharp code is something a toddler can do, just use the rules described here: http://stackoverflow.com/a/29600433/1622493 – Bruno Lowagie Apr 13 '15 at 17:11

1 Answers1

1

Please take a look at the SimpleTable7 example and compare the Java code with your [?] code:

This part is relevant:

PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.setColspan(5);
cellImportantNote.setBorder(PdfPCell.NO_BORDER);
table.addCell(cellImportantNote);

If I would convert your [?] code to Java, you'd have:

PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.setColspan(5);
cellImportantNote.setBorder(PdfPCell.NO_BORDER);
table.addCell(importantNotice);

Do you see the difference? You create a cellImportantNote instance, but you aren't using it anywhere. Instead of adding cellImportantNote to the table, you add the importantNotice paragraph.

This means that you are creating a table with 10 columns that has a single row of which only 6 cells are taken (because you have 1 cell with colspan 3, 1 cell with colspan 2 and 1 cell with colspan 1).

By default, iText doesn't render any rows that aren't complete, and since your table doesn't have any complete row, the table isn't being rendered.

If you look at the resulting PDF, simple_table7.pdf, you'll notice that I also added a second table. This table has only three columns, but it looks identical to the table you constructed. Instead of improper use of the colspan functionality, I defined relative widths for the three columns:

table = new PdfPTable(3);
table.setWidths(new int[]{3, 2, 5});
cell.setColspan(1);
table.addCell(cell);
cellCaveat.setColspan(1);
table.addCell(cellCaveat);
cellImportantNote.setColspan(1);
table.addCell(cellImportantNote);
document.add(table);

Note that I also avoid to use meaningless numbers. For instance, instead of:

cell.setHorizontalAlignment(0); // 0 means left

I use:

cell.setHorizontalAlignment(Element.ALIGN_LEFT);

This way, people can read what this line means without having to depend on comments.

Furtermore, I replaced:

 cell.setBorderWidth(0);

with:

 cell.setBorder(PdfPCell.NO_BORDER);

That too, is only a matter of taste, but I think it's important if you want to keep your code maintainable.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • This is useful, but what I need is those three elements in three different rows, not three different columns. Basically, I just need to restrict the red text to the left half of the page, rather than taking up the entire width of the page, and was hoping a single-row, borderless table would be the easiest way to do that. – B. Clay Shannon-B. Crow Raven Apr 13 '15 at 15:36
  • I don't understand why you'd use a table to mimic indentation. Why not increase the left indentation of the paragraph with the red text? – Bruno Lowagie Apr 13 '15 at 17:08
  • I don't want indentation; I changed it so that it was NOT centered (which it was, for some reason). It is now hugging the left edge, as I want. – B. Clay Shannon-B. Crow Raven Apr 13 '15 at 17:28