一个单元格具有不同的边框类型 [英] One cell with different border types

查看:80
本文介绍了一个单元格具有不同的边框类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试创建虚线单元格时,我正在使用PdfPCellEvent,如

When I try to create a dotted cell I am using the PdfPCellEvent as described in example. However I get all of the borders drawn with dotted line. When I set up the cell.setBorder(Rectangle.BOTTOM | Rectangle.RIGHT); the bottom and right got drawn with solid line. When I remove the setBorder I got all borders dotted.

  1. 如何绘制带有实心,虚线和NO_BORDER三种类型的边框的单元格.我从图片中寻找一个示例性的简单表格.蓝线代表NO_BORDER.
  2. 两个单元格共享一个边界时,虚线重叠并合并为实线.避免它的唯一方法是从其中一个单元中删除共享边框?
  1. How to draw a cell with three types of borders solid, dotted and NO_BORDER. I am after an exemplary simple table from the picture. Where the blue lines stands for NO_BORDER.
  2. While two cells share one border the dotted line overlaps and combines into solid line. The only way to avoid it is to remove the shared border form one of the cells?

推荐答案

我认为您正在混淆.

如果使用单元格事件绘制边框,则创建自定义边框,则应删除所有自动边框.因此,您始终需要:

If you use cell events to draw borders, you create custom borders, you should remove all automated borders. So you always need:

 cell.setBorder(PdfPCell.NO_BORDER);

如果要绘制局部边框,则需要绘制局部边框.

If you want to draw partial borders, you need to draw partial borders.

在您引用的示例中,使用moveTo()lineTo()stroke()命令序列添加了许多行.换句话说:决定绘制哪条线.

In the example you refer to, you add a number of lines using a sequence of moveTo(), lineTo() and stroke() commands. In other words: you decide which lines are drawn.

很难理解为什么当 you 是绘制线条的人时,为什么会抱怨自己绘制了所有边框".如果要减少绘制的边框数量,请减少线条.

It is hard to understand why you'd complain that you "get all of the borders drawn" when you are the one drawing the lines. If you want to reduce the number of borders drawn, draw less lines.

您应该省略哪几行?这不是我们来决定的:您知道您的需要;您知道您所需要的.你应该决定!

Which lines should you omit? That's not up to us to decide: you know what you need; you should decide!

请查看

Please take a look at the DottedLineCell2 example. This is a variation on the example you refer to. In this example, I create an event that draws each border separately:

class DottedCell implements PdfPCellEvent {
    private int border = 0;
    public DottedCell(int border) {
        this.border = border;
    }
    public void cellLayout(PdfPCell cell, Rectangle position,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.saveState();
        canvas.setLineDash(0, 4, 2);
        if ((border & PdfPCell.TOP) == PdfPCell.TOP) {
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getTop());
        }
        if ((border & PdfPCell.BOTTOM) == PdfPCell.BOTTOM) {
            canvas.moveTo(position.getRight(), position.getBottom());
            canvas.lineTo(position.getLeft(), position.getBottom());
        }
        if ((border & PdfPCell.RIGHT) == PdfPCell.RIGHT) {
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getRight(), position.getBottom());
        }
        if ((border & PdfPCell.LEFT) == PdfPCell.LEFT) {
            canvas.moveTo(position.getLeft(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getBottom());
        }
        canvas.stroke();
        canvas.restoreState();
    }
}

在创建此事件的实例时,必须传递border值.在cellLayout()方法中,我们将查看以下边框值:

When creating an instance of this event, you have to pass a border value. In the cellLayout() method, we'll look at this border value:

  • 选择TOP位时,我们将从右上角到左上角构建一条线,
  • 选择BOTTOM位时,我们将从右下角到左下角构建一条线,
  • 选择RIGHT位时,我们将从右上角到右下角构建一条线,
  • 选择LEFT位时,我们将从左上角到左下角构造一条线.
  • When the TOP bit is selected, we construct a line from the upper-right corner to the upper-left corner,
  • When the BOTTOM bit is selected, we construct a line from the lower-right corner to the lower-left corner,
  • When the RIGHT bit is selected, we construct a line from the upper-right corner to the lower-right corner,
  • When the LEFT bit is selected, we construct a line from the upper-left corner to the lower-left corner.

检查完边框的所有边后,我们stroke()线.

Once we've checked all the sides of the border, we stroke() the lines.

在下面的示例中,我创建了两个表:

In the following example, I create two tables:

public void createPdf(String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(dest));
    document.open();

    PdfPTable table;
    PdfPCell cell;

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("left border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.LEFT));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("right border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.RIGHT));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.TOP));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.BOTTOM));
    table.addCell(cell);
    document.add(table);

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("left and top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.LEFT | PdfPCell.TOP));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("right and bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.RIGHT | PdfPCell.BOTTOM));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("no border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("full border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedCell(PdfPCell.BOX));
    table.addCell(cell);
    document.add(table);
    document.close();
}

这是两个表的外观: dotted_line_cell2.pdf

更新2

在您的评论中,您声称我的回答还不够,这说明您的编程技能相当有限:您无法将单元格事件改编为绘制不同类型边界的事件.关于我的最初示例,您还问这是唯一的方法吗?"

In your comment you claim that my answer isn't sufficient, explaining that your programming skills are rather limited: you can't adapt the cell event into an event that draws different types of borders. With respect to my initial example, you also ask "is it the only way?"

当然,这不是唯一的方法:有许多不同的方法可以实现您想要的结果.请允许我提出两个额外的示例(尽管还有更多可能的变体,其中一些可能涉及表事件而不是单元事件):

Of course it's not the only way: there are many different way to achieve the result you desire. Allow me to present two extra examples (although there are many more possible variations, some of which might involve table events instead of cell events):

其他示例#1:使用界面定义破折号:

CustomBorder3中示例,我复制/粘贴了上一个示例中的单元格事件,并进行了如下修改:

In the CustomBorder3 example, I copy/pasted the cell event from my previous example and I adapted it like this:

class CustomBorder implements PdfPCellEvent {
    protected LineDash left;
    protected LineDash right;
    protected LineDash top;
    protected LineDash bottom;
    public CustomBorder(LineDash left, LineDash right,
            LineDash top, LineDash bottom) {
        this.left = left;
        this.right = right;
        this.top = top;
        this.bottom = bottom;
    }
    public void cellLayout(PdfPCell cell, Rectangle position,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        if (top != null) {
            canvas.saveState();
            top.applyLineDash(canvas);
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getTop());
            canvas.stroke();
            canvas.restoreState();
        }
        if (bottom != null) {
            canvas.saveState();
            bottom.applyLineDash(canvas);
            canvas.moveTo(position.getRight(), position.getBottom());
            canvas.lineTo(position.getLeft(), position.getBottom());
            canvas.stroke();
            canvas.restoreState();
        }
        if (right != null) {
            canvas.saveState();
            right.applyLineDash(canvas);
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getRight(), position.getBottom());
            canvas.stroke();
            canvas.restoreState();
        }
        if (left != null) {
            canvas.saveState();
            left.applyLineDash(canvas);
            canvas.moveTo(position.getLeft(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getBottom());
            canvas.stroke();
            canvas.restoreState();
        }
    }
}

如您所见,我不再定义border值,而是定义了四个值:leftrighttopbottom.在cellLayout()方法中,我为与null不同的每个值绘制一条线.

As you can see, I no longer define a border value, but instead I define four values: left, right, top, and bottom. In the cellLayout() method, I draw a line for each of those values that is different from null.

变量的类型为LineDash. LineDash是具有单个方法的接口:

The variables are of type LineDash. LineDash is an interface with a single method:

interface LineDash {
    public void applyLineDash(PdfContentByte canvas);
}

我为此接口创建了三个实现:

I created three implementations for this interface:

class SolidLine implements LineDash {
    public void applyLineDash(PdfContentByte canvas) { }
}

class DottedLine implements LineDash {
    public void applyLineDash(PdfContentByte canvas) {
        canvas.setLineCap(PdfContentByte.LINE_CAP_ROUND);
        canvas.setLineDash(0, 4, 2);
    }
}

class DashedLine implements LineDash {
    public void applyLineDash(PdfContentByte canvas) {
        canvas.setLineDash(3, 3);
    }
}

您可以轻松创建新的实现,例如:

You can easily create new implementations such as:

class DashedLine2 implements LineDash {
    float unitsOn;
    float phase;
    public DashedLine2(float unitsOn, float phase) {
        this.unitsOn = unitsOn;
        this.phase = phase;
    }
    public void applyLineDash(PdfContentByte canvas) {
        canvas.setLineDash(unitsOn, phase);
    }
}

您甚至可以引入一种更改边框的颜色和宽度的实现.

You could even introduce an implementation that changes the color and the width of the border.

我现在可以像这样使用CustomBorder事件:

I can now use the CustomBorder event like this:

public void createPdf(String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(dest));
    document.open();

    PdfPTable table;
    PdfPCell cell;
    LineDash solid = new SolidLine();
    LineDash dotted = new DottedLine();
    LineDash dashed = new DashedLine();

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("dotted left border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(dotted, null, null, null));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("solid right border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(null, solid, null, null));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("dashed top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(null, null, dashed, null));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(null, null, null, solid));
    table.addCell(cell);
    document.add(table);

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("dotted left and solid top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(dotted, null, solid, null));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("dashed right and dashed bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(null, dashed, null, dashed));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("no border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("full solid border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new CustomBorder(solid, solid, solid, solid));
    table.addCell(cell);
    document.add(table);
    document.close();
}

结果如下:

其他示例#2:使用抽象类作为单元事件的基础:

CustomBorder4中示例,我复制/粘贴了上一个示例中的单元格事件,并进行了如下修改:

In the CustomBorder4 example, I copy/pasted the cell event from my previous example and I adapted it like this:

abstract class CustomBorder implements PdfPCellEvent {
    private int border = 0;
    public CustomBorder(int border) {
        this.border = border;
    }
    public void cellLayout(PdfPCell cell, Rectangle position,
        PdfContentByte[] canvases) {
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.saveState();
        setLineDash(canvas);
        if ((border & PdfPCell.TOP) == PdfPCell.TOP) {
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getTop());
        }
        if ((border & PdfPCell.BOTTOM) == PdfPCell.BOTTOM) {
            canvas.moveTo(position.getRight(), position.getBottom());
            canvas.lineTo(position.getLeft(), position.getBottom());
        }
        if ((border & PdfPCell.RIGHT) == PdfPCell.RIGHT) {
            canvas.moveTo(position.getRight(), position.getTop());
            canvas.lineTo(position.getRight(), position.getBottom());
        }
        if ((border & PdfPCell.LEFT) == PdfPCell.LEFT) {
            canvas.moveTo(position.getLeft(), position.getTop());
            canvas.lineTo(position.getLeft(), position.getBottom());
        }
        canvas.stroke();
        canvas.restoreState();
    }

    public abstract void setLineDash(PdfContentByte canvas);
}

该类是抽象的,因为它包含未实现的方法.我现在可以像这样扩展这个抽象类:

This class is abstract, because it contains a method that isn't implemented. I can now extend this abstract class like this:

class SolidBorder extends CustomBorder {
    public SolidBorder(int border) { super(border); }
    public void setLineDash(PdfContentByte canvas) {}
}
class DottedBorder extends CustomBorder {
    public DottedBorder(int border) { super(border); }
    public void setLineDash(PdfContentByte canvas) {
        canvas.setLineCap(PdfContentByte.LINE_CAP_ROUND);
        canvas.setLineDash(0, 4, 2);
    }
}
class DashedBorder extends CustomBorder {
    public DashedBorder(int border) { super(border); }
    public void setLineDash(PdfContentByte canvas) {
        canvas.setLineDash(3, 3);
    }
}

同样,我可以引入不同的参数来更改虚线图案,颜色,线宽等.但这是您可以轻松完成的事情.

Again, I could introduce different parameters to change the dash pattern, color, line width, etc. But that's something you can easily do yourself.

我现在可以在不同的单元格或同一单元格上使用三个不同的单元格事件:

I have now three different cell events that I can use on different cells or on the same cell:

public void createPdf(String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(dest));
    document.open();

    PdfPTable table;
    PdfPCell cell;

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("dotted left border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedBorder(PdfPCell.LEFT));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("solid right border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new SolidBorder(PdfPCell.RIGHT));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("solid top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new SolidBorder(PdfPCell.TOP));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("dashed bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DashedBorder(PdfPCell.BOTTOM));
    table.addCell(cell);
    document.add(table);

    table = new PdfPTable(4);
    table.setSpacingAfter(30);
    cell = new PdfPCell(new Phrase("dotted left and dashed top border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedBorder(PdfPCell.LEFT));
    cell.setCellEvent(new DashedBorder(PdfPCell.TOP));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("solid right and dotted bottom border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedBorder(PdfPCell.BOTTOM));
    cell.setCellEvent(new SolidBorder(PdfPCell.RIGHT));
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("no border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    table.addCell(cell);
    cell = new PdfPCell(new Phrase("full border"));
    cell.setBorder(PdfPCell.NO_BORDER);
    cell.setCellEvent(new DottedBorder(PdfPCell.LEFT | PdfPCell.RIGHT));
    cell.setCellEvent(new SolidBorder(PdfPCell.TOP));
    cell.setCellEvent(new DashedBorder(PdfPCell.BOTTOM));
    table.addCell(cell);
    document.add(table);
    document.close();
}

结果如下:

这些只是 两个额外的示例.一个人可以轻松编写更多内容.如果您还有其他问题(例如:如何更改边框的颜色),请创建一个新问题并显示您编写的代码,并解释为什么它不能给您期望的结果.

These are only two extra examples. One could easily write many more. If you have any further question (e.g.: how to change the color of a border), please create a new question and show the code you have written, explaining why it doesn't give you the result you expect.

这篇关于一个单元格具有不同的边框类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆