SetMargin on Cell not working in itext7 .NET library

0 votes
asked Sep 6, 2017 by missinglinq

I am attempting to recreate the CellMarginPadding example found here using C#:

http://developers.itextpdf.com/content/itext-7-building-blocks/examples/chapter-5#2035-c05e05_cellmarginpadding.java

Everything works as expected EXCEPT the margins. There are no margins at all set on the cells on which SetMargin(), SetMarginBottom(), or SetMarginTop() is called.

My C# code is a direct port as seen below:

        //Initialize PDF document
        PdfDocument pdf = new PdfDocument(new PdfWriter(dest));

        // Initialize document
        Document document = new Document(pdf);

        Table table = new Table(new float[] {2, 1, 1});
        table.SetBackgroundColor(Color.ORANGE);
        table.SetWidthPercent(80);
        table.SetHorizontalAlignment(HorizontalAlignment.CENTER);

        table.AddCell(new Cell(1, 3).Add("Cell with colspan 3")
            .SetPadding(10).SetMargin(5).SetBackgroundColor(Color.GREEN));

        table.AddCell(new Cell(2, 1).Add("Cell with rowspan 2")
            .SetMarginTop(5).SetMarginBottom(5).SetPaddingLeft(30)
            .SetFontColor(Color.WHITE).SetBackgroundColor(Color.BLUE));

        table.AddCell(new Cell().Add("row 1; cell 1")
            .SetFontColor(Color.WHITE).SetBackgroundColor(Color.RED));

        table.AddCell(new Cell().Add("row 1; cell 2"));

        table.AddCell(new Cell().Add("row 2; cell 1").SetMargin(10)
            .SetFontColor(Color.WHITE).SetBackgroundColor(Color.RED));

        table.AddCell(new Cell().Add("row 2; cell 2").SetPadding(10)
            .SetFontColor(Color.WHITE).SetBackgroundColor(Color.RED));

        document.Add(table);

        document.Close();

Am I doing this wrong? Or is it possible there is a bug in the itext7 .NET library?

2 Answers

0 votes
answered Sep 7, 2017 by joris-schellekens

There's a tutorial for this on the iText website.

Check out https://developers.itextpdf.com/examples/tables/clone-alignment-indentation-leading-and-spacing-cells for a code sample.

protected void manipulatePdf(String dest) throws Exception {

    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);

    PdfCanvas cb = new PdfCanvas(pdfDoc.addNewPage());
    cb.moveTo(36, 842);
    cb.lineTo(36, 0);
    cb.stroke();
    Table table = new Table(8);
    table.setHorizontalAlignment(HorizontalAlignment.LEFT);
    table.setWidth(150);
    for (int aw = 0; aw < 16; aw++) {
        table.addCell(new Cell().add(new Paragraph("hi")));
    }
    table.setMarginLeft(25);
    doc.add(table);

    doc.close();
}
0 votes
answered Sep 11, 2017 by bruno-lowagie

I think that you want the reintroduction of a bug that existed in iText 7.0.0.

I have converted your code sample to HTML:

<table style="background: orange; text-align: center; width: 80%" border="0" cellspacing="0" align="center">
<tr>
    <td colspan="3" style="padding: 10pt; margin: 5pt; background: green;">Cell with colspan 3</td>
</tr>
<tr>
    <td rowspan="2" style="color: white; background: blue; margin-top: 5pt; margin-bottom: 30pt; padding-left: 30pt">Cell with rowspan 2</td>
    <td style="color: white; background: red">row 1; cell 1</td>
    <td>row 1; cell 2</td>
</tr>
<tr>
    <td style="color: white; background: red; margin: 10pt;">row 2; cell 1</td>
    <td style="color: white; background: red; padding: 10pt;">row 2; cell 2</td>
</tr>
</table>

I converted the values for the margins, paddings, colors,... in your C# code to inline CSS values in the HTML. Then I converted that HTML to PDF.

You can see the HTML and the PDF in the following screen shot:

enter image description here

Wouldn't you agree that the PDF looks as expected?

If you want us to look into this matter, please provide some HTML code that creates a table that shows exactly what it is that you want to achieve when you define a margin. It would be interesting for us to check if pdfHTML converts that HTML to PDF that looks more or less identical. If it does, and if you really want to code your table, you can then use the code that is used by pdfHTML (an add-on on top of iText 7) to mimic the same result straight from code.

Update:

Because of your question, I have started updating chapter 5 of the Building Blocks tutorial. I still have plenty of work to do, but I can already tell you what I discovered.

As I already mentioned in my initial answer, margins are ignored in Cell objects because CSS margins are ignored in HTML table cells. The iText 7 CellRenderer code was changed in function of the pdfHTML add-on:

@Override
protected Rectangle applyMargins(Rectangle rect, float[] margins, boolean reverse) {
    // Do nothing here. Margins shouldn't be processed on cells.
    return rect;
}

Of course, if you want to get the original behavior, you can override the CellRenderer. That's what I did in the CellMarginPadding2 example:

private class MarginCellRenderer extends CellRenderer {
    public MarginCellRenderer(Cell modelElement) {
        super(modelElement);
    }

    @Override
    protected Rectangle applyMargins(Rectangle rect, float[] margins, boolean reverse) {
        return rect.<Rectangle>applyMargins(margins[0], margins[1], margins[2], margins[3], reverse);
    }
}

private class MarginCell extends Cell {
    public MarginCell() {
        super();
    }

    public MarginCell(int rowspan, int colspan) {
        super(rowspan, colspan);
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new MarginCellRenderer(this);
    }
}

public static void main(String args[]) throws IOException {
    File file = new File(DEST);
    file.getParentFile().mkdirs();
    new C05E05_CellMarginPadding2().createPdf(DEST);
}

public void createPdf(String dest) throws IOException {
    //Initialize PDF document
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));

    // Initialize document
    Document document = new Document(pdf);
    Table table = new Table(UnitValue.createPercentArray(new float[]{2, 1, 1}));
    table.setBackgroundColor(Color.ORANGE);
    table.setWidthPercent(80);
    table.setHorizontalAlignment(HorizontalAlignment.CENTER);
    table.addCell(
        new MarginCell(1, 3).add("Cell with colspan 3")
            .setPadding(10).setMargin(5).setBackgroundColor(Color.GREEN));
    table.addCell(new MarginCell(2, 1).add("Cell with rowspan 2")
        .setMarginTop(5).setMarginBottom(5).setPaddingLeft(30)
        .setFontColor(Color.WHITE).setBackgroundColor(Color.BLUE));
    table.addCell(new MarginCell().add("row 1; cell 1")
        .setFontColor(Color.WHITE).setBackgroundColor(Color.RED));
    table.addCell(new MarginCell().add("row 1; cell 2"));
    table.addCell(new MarginCell().add("row 2; cell 1").setMargin(10)
        .setFontColor(Color.WHITE).setBackgroundColor(Color.RED));
    table.addCell(new MarginCell().add("row 2; cell 2").setPadding(10)
        .setFontColor(Color.WHITE).setBackgroundColor(Color.RED));
    document.add(table);
    document.close();
}

I created a MarginCell class that renders cells using the MarginCellRenderer. In that renderer, I override the applyMargins() method, so that the margins are no longer ignored.

This fixes your problem. Changes to chapter 5 of the tutorial will be applied as soon as possible (depending on how many people demand my time on Stack Overflow :D ).

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...