Nanda
Nanda

Reputation: 45

How to use a dotted line as a cell border?

I am trying to get dotted border (used cell border) in middle of the table by using iText 2.1.0. Below code would be generating dotted border even after middle of the table.

Could you please help me on this to add event for a specific cell alone?

import java.io.FileOutputStream;

import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

public class DottedLine {

    public static final String RESULT = "Dotted.pdf";

    public static void main(String[] args) throws Exception {
        new DottedLine().createPdf(RESULT);
    }

    public void createPdf(String filename) throws Exception {

        Document document = new Document(PageSize.A4, 50, 50, 50, 50);

        PdfWriter.getInstance(document, new FileOutputStream(filename));

        document.open();

        PdfPTable tab = new PdfPTable(1);
        for (int j = 1; j <= 10; j++) {
            if (j == 5) {
                PdfPCell c1 = new PdfPCell(new Phrase("Test" + j));
                c1.setBorder(Rectangle.TOP);
                c1.setCellEvent(new dot());
                tab.addCell(c1);
            } else {
                PdfPCell c2 = new PdfPCell(new Phrase("Test " + j));
                c2.setBorder(Rectangle.TOP);
                tab.addCell(c2);
            }
        }

        document.add(tab);
        document.close();
    }

    // Cell Event to make dotted Line
    class dot implements PdfPCellEvent {

        @Override
        public void cellLayout(PdfPCell arg0, Rectangle arg1, PdfContentByte[] arg2) {
            arg0.setBorder(Rectangle.TOP);
            PdfContentByte cb = arg2[PdfPTable.LINECANVAS];
            cb.setLineDash(3f, 3f);
            cb.restoreState();
        }
    }
}

Upvotes: 3

Views: 6741

Answers (1)

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

You're using a cell event, but your code is very poor. You're also introducing a PDF syntax error for which you would have received a warning if only you would use a more recent version of iText. (The warnings about obsolete iText versions are there for a reason. People shouldn't ignore them!!!)

This being said, I've made an example that solves your problem: DottedLineCell

The resulting PDF is a document with two tables: dotted_line_cell.pdf

For the first table, we use a table event:

class DottedCells implements PdfPTableEvent {
    @Override
    public void tableLayout(PdfPTable table, float[][] widths,
        float[] heights, int headerRows, int rowStart,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.setLineDash(3f, 3f);
        float llx = widths[0][0];
        float urx = widths[0][widths[0].length -1];
        for (int i = 0; i < heights.length; i++) {
            canvas.moveTo(llx, heights[i]);
            canvas.lineTo(urx, heights[i]);
        }
        for (int i = 0; i < widths.length; i++) {
            for (int j = 0; j < widths[i].length; j++) {
                canvas.moveTo(widths[i][j], heights[i]);
                canvas.lineTo(widths[i][j], heights[i+1]);
            }
        }
        canvas.stroke();
    }
}

This is the most elegant way to draw the cell borders, as it uses only one stroke() operator for all the lines. This isn't an option if you have tables with rowspans (but you probably don't care about rowspans, because you're using an obsolete version of iText that didn't support rowspans).

The second table uses a cell event:

class DottedCell implements PdfPCellEvent {
    @Override
    public void cellLayout(PdfPCell cell, Rectangle position,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.setLineDash(3f, 3f);
        canvas.rectangle(position.getLeft(), position.getBottom(),
            position.getWidth(), position.getHeight());
        canvas.stroke();
    }
}

With a cell event, a border is drawn around every cell. This means you'll have multiple stroke() operators and overlapping lines.

May I plead once more that you upgrade to a more recent version? Pre-iText 5 versions have a peculiar error that leads to table rows that disappear once in a billion rows.

Upvotes: 4

Related Questions