Graham Harris Graham Harris - 3 days ago 4
C# Question

Problems with Version 7 of iText PDF for C#

I am using iText PDF to generate a PDF file that contains a table that should be laid out as follows:

------------------------------------------------
| HEADER |
------------------------------------------------
| some data goes here | more data here |
------------------------------------------------
| Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 |
------------------------------------------------
| 1 | SDF wer qwerwq | weqr | WERQW |
------------------------------------------------
| | | | |
| | | | |
| | | | |
| | | | |
------------------------------------------------
| footer information |
------------------------------------------------


however the table is being drawn as follows:

------------------------------------------------
| HEADER |
------------------------------------------------
| some data goes here | more data here |
------------------------------------------------
| Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 |
------------------------------------------------
| 1 | SDF | wer | qwerwq | weqr | WERQW |
------------------------------------------------
| | | | |
------------------------------------------------
| | | | |
------------------------------------------------
| | | | |
------------------------------------------------
| | | | |
------------------------------------------------
| footer information |
------------------------------------------------


I have tried following the examples but they are written in Java, and the Object model for C# appears to be subtly different. The rows below the row that has a "Col 1" value of 1 are split across Columns 2, 3, and 4.

Points to note:


  1. For the header cell I am setting the horizontal alignment by calling cell.SetHorizontalAlignment(HorizontalAlignment.CENTER)

  2. I need to set the colour of some of the text to be red

  3. I am using the table.AddCell method to add the cell

  4. I am setting the border of the table (according to the documentation this is the default cell) to Border.NO_BORDER.

  5. This is for a web app written in C#

  6. I have downloaded the latest version of iText (version 7.0.1)

  7. I have created a custom CellRender but that appears to have no effect.

  8. Originally I was using iText 5 but I needed greater control over the rendering of the table as I needed to know how far down the page we have reached.

  9. This is the code that I use to create the cell:

    PdfFont cellFont = font;

    if ((fontStyle & FONT_STYLE_BOLD) == FONT_STYLE_BOLD && (fontStyle & FONT_STYLE_ITALIC) == FONT_STYLE_ITALIC)
    {
    cellFont = fontBoldItalic;
    }
    else if ((fontStyle & FONT_STYLE_BOLD) == FONT_STYLE_BOLD)
    {
    cellFont = fontBold;
    }
    else if ((fontStyle & FONT_STYLE_ITALIC) == FONT_STYLE_ITALIC)
    {
    cellFont = fontItalic;
    }

    Color fontColor = Color.BLACK;
    if ((fontStyle & FONT_STYLE_RED) == FONT_STYLE_RED)
    {
    fontColor = Color.RED;
    }

    Text text = new Text(content);
    text.SetFont(cellFont);
    text.SetFontColor(fontColor);
    text.SetFontSize(fontSize);

    if ((fontStyle & FONT_STYLE_UNDERLINE) == FONT_STYLE_UNDERLINE)
    {
    text.SetUnderline();
    }

    Cell cell = new Cell(rowspan, colspan);
    cell.Add(new Paragraph(text));
    //cell.SetNextRenderer(new CellBorders(cell, borders));

    return cell;



This is how the table is created and the table is added to the document at the end of the web method:

Table table = new Table(6);
table.SetWidthPercent(100);
table.SetPadding(3);
table.SetSpacingRatio(1);
table.SetBorder(Border.NO_BORDER);

Answer

You have two problems here:

  1. Text not aligning properly (Header) Text alignment in cells is set using the SetTextAlignment() method. SetHorizontalAlignment sets the alignment of the container wrapping the text.

  2. borders not displaying as expected. First, defining border on a table does not define default cell behaviour in iText 7, like it does in iText 5. Since the default tableRenderer does not make use of the border property, table#SetBorder(Border.NO_BORDER) will have no effect unless you define a custom renderer and make use of the property yourself.

The correct way to define custom borders is to do it on the level of individual cells. And here you need to remember that since borders overlap, you need to set all overlapping borders to NO_BORDER if you don't want the border to show:

    for(int j = 0; j<3; j++){
        Cell dCell = new Cell();
        //When setting borders to NO_BORDER, remember to set that border to NO_BORDER in all adjoining cells
        dCell.SetBorderLeft(Border.NO_BORDER);
        dCell.SetBorderRight(Border.NO_BORDER);
        dCell.Add(new Paragraph(String.Format("Entry, {0}-{1}",i,j)));
        //Dashed, striped, grooved and more can be specified
        if(i != 4) dCell.SetBorderBottom(new DashedBorder(1f));
        tab.AddCell(dCell);
    }

The above fragment will result in cells with no borders between the entries.

    for(int k = 4; k<6;k++){
        Cell d2Cell = new Cell();
        //Only the right-most border will not show, since the left-most borders of the neighbouring cells still get drawn
        d2Cell.SetBorderRight(Border.NO_BORDER);
        d2Cell.Add(new Paragraph(String.Format("Entry, {0}-{1}",i,k)).SetFontColor(Color.RED));
        //Specific borders apart from NO_BORDER do override the default
        if(i!=4) d2Cell.SetBorderBottom(new DashedBorder(1f));
        tab.AddCell(d2Cell);
    }

The above fragment will only have no border on the right of the right-most cell.

Below is a self-contained code fragment that constructs a table like the one in the question:

    public void CreateTable(string dest)
    {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);

        Table tab = new Table(6);
        //Table should take up the entire width
        tab.SetWidthPercent(100);
        tab.SetPadding(3);
        //Because table takes up the entire width, this has no visual effect, but otherwise it will center the table
        tab.SetHorizontalAlignment(HorizontalAlignment.CENTER);


        //Header cell
        Cell hCell = new Cell(1, 6);
        hCell.Add(new Paragraph("Centered Header"));
        //Text is aligned by calling SetTextAlignment
        hCell.SetTextAlignment(TextAlignment.CENTER);

        tab.AddCell(hCell);
        //Subheaders
        Cell shCellL = new Cell(1, 3);
        shCellL.Add(new Paragraph("Left aligned data"));
        shCellL.SetTextAlignment(TextAlignment.LEFT);

        Cell shCellR = new Cell(1, 3);
        shCellR.Add(new Paragraph("Right aligned data"));
        shCellR.SetTextAlignment(TextAlignment.RIGHT);

        tab.AddCell(shCellL);
        tab.AddCell(shCellR);
        //col names
        for (int i = 0; i < 6; i++)
        {
            Cell colName = new Cell();
            colName.Add(new Paragraph(String.Format("Col {0}", i)));
            colName.SetTextAlignment(TextAlignment.CENTER);
            tab.AddCell(colName);
        }
        //data cols
        for (int i = 1; i < 5; i++)
        {
            Cell nC = new Cell();
            nC.Add(new Paragraph("" + i));
            tab.AddCell(nC);
            for (int j = 0; j < 3; j++)
            {
                Cell dCell = new Cell();
                //When Setting borders to NO_BORDER, remember to Set that border to NO_BORDER in all adjoining cells
                dCell.SetBorderLeft(Border.NO_BORDER);
                dCell.SetBorderRight(Border.NO_BORDER);
                dCell.Add(new Paragraph(String.Format("Entry, {0}-{1}", i, j)));
                //Dashed, striped, grooved and more can be specified
                if (i != 4) dCell.SetBorderBottom(new DashedBorder(1f));
                tab.AddCell(dCell);
            }
            for (int k = 4; k < 6; k++)
            {
                Cell d2Cell = new Cell();
                //Only the rightmost border will not show, since the left-most borders of the neighbouring cells still get drawn
                d2Cell.SetBorderRight(Border.NO_BORDER);
                d2Cell.Add(new Paragraph(String.Format("Entry, {0}-{1}", i, k)).SetFontColor(Color.RED));
                //Specific borders apart from NO_BORDER do override the default
                if (i != 4) d2Cell.SetBorderBottom(new DashedBorder(1f));
                tab.AddCell(d2Cell);
            }
        }

        //footer cell
        Cell fCell = new Cell(1, 6);
        fCell.Add(new Paragraph("footer"));
        tab.AddCell(fCell);

        //Add table to document
        doc.Add(new Paragraph("Complex Table example"));
        doc.Add(tab);
        doc.Close();
    }
Comments