C# Itextsharp PDFPTable如何在整个表格周围创建边框

C# Itextsharp PDFPTable如何在整个表格周围创建边框,c#,itext,C#,Itext,我正在使用PDFPTable通过Itextsharp中的数据库构建一个表,要求表中的行/单元格没有上边框或下边框,但每个单元格的左右两侧都有一个黑色边框(换句话说,每列都有一个左右边框),桌子的底部也需要用黑色边框封闭,这就是我的问题所在 我要做的是将边框设置为0,然后手动分配边框,以便只获取每个单元格上的左边框和右边框,如下所示为生成“数量”列的示例: cell = new PdfPCell(new Phrase(Qty.value, subheaderFont)); cell

我正在使用PDFPTable通过Itextsharp中的数据库构建一个表,要求表中的行/单元格没有上边框或下边框,但每个单元格的左右两侧都有一个黑色边框(换句话说,每列都有一个左右边框),桌子的底部也需要用黑色边框封闭,这就是我的问题所在

我要做的是将边框设置为0,然后手动分配边框,以便只获取每个单元格上的左边框和右边框,如下所示为生成“数量”列的示例:

    cell = new PdfPCell(new Phrase(Qty.value, subheaderFont));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    cell.VerticalAlignment = Element.ALIGN_MIDDLE; 
    cell.BackgroundColor = new iTextSharp.text.BaseColor(220, 220, 220);
    cell.Border = 0;
    cell.BorderColorLeft = BaseColor.BLACK;
    cell.BorderWidthLeft = .5f;
    cell.BorderColorRight = BaseColor.BLACK;
    cell.BorderWidthRight = .5f;
    table.AddCell(cell); 
问题很明显,我无法检测最后一行来添加边框底部,但我认为必须有一种方法来控制“表”本身的边框,还是我采取了错误的方法?

正如您所发现的,没有边框,可能是因为PDF一开始就没有表格。将边界直接放在边界上可能更有意义(尽管PDF也不支持这些)。不管怎样,一个表只是一个单元格的集合,所以让它们来处理它吧

无论如何,解决方案是在
PdfPTable
类的实例上设置
TableEvent
。要做到这一点,您需要该接口的自定义实现。下面的代码通常可以为您做到这一点(参见底部的注释中的“一般”)

类TopBottomTableBorderMaker:IPdfPTableEvent{
私人BaseColor\u borderColor;
私有浮动(u)边界宽度;
/// 
///向表中添加上边框和下边框。
/// 
///边框的颜色。
///边界的宽度
公共TopBottomTableBorderMaker(基色borderColor、浮动边框宽度){
这是。_borderColor=borderColor;
这是。_borderWidth=borderWidth;
}
公共void表格布局(PdfPTable表格、浮点[][]宽度、浮点[]高度、int headerRows、int rowStart、PdfContentByte[]画布){
//宽度(应该被认为是x)是一个数组数组,第一个索引用于每行,第二个索引用于每列
//下面使用“第一个”和“最后一个”来计算每个X的起点和终点
var firstRowWidths=宽度[0];
var lastRowWidths=宽度[widths.Length-1];
var firstRowXStart=firstRowWidths[0];
var firstRowXEnd=firstRowWidths[firstRowWidths.Length-1]-firstRowXStart;
var lastRowXStart=lastRowWidths[0];
var lastRowXEnd=lastRowWidths[lastRowWidths.Length-1]-lastRowXStart;
//高度(应该被认为是y的)是每行顶部的y加上最后一行底部的一个额外值
//下面使用“第一个”和“最后一个”来计算每个Y的起点和终点
var firstRowYStart=高度[0];
var firstRowYEnd=高度[1]-firstRowYStart;
var lastRowYStart=heights[heights.Length-1];
var lastRowYEnd=heights[heights.Length-2]-lastRowYStart;
//我们要在哪里划清界限
PdfContentByte canvas=画布[PdfPTable.LINECANVAS];
//在改变任何事情之前,我总是试图保存以前的状态
canvas.SaveState();
//设置我们的行属性
canvas.SetLineWidth(此._borderWidth);
canvas.SetColorStroke(此._borderColor);
//画一些长方形
画布。矩形(
firstRowXStart,
第一排,
firstRowXEnd,
第一排
);
//直到你抚摸它们,它们才真正被画出来!
canvas.Stroke();
画布。矩形(
lastRowXStart,
lastRowYStart,
lastRowXEnd,
末日
);
canvas.Stroke();
//恢复任何以前的设置
canvas.RestoreState();
}
}
使用它非常简单,只需将实例绑定到属性:

//Create your name as you normally do
var table = new PdfPTable(3);

//Bind and instance with properties set
table.TableEvent = new TopBottomTableBorderMaker(BaseColor.BLACK, 0.5f);

//The rest is the same
for (var i = 0; i < 6; i++) {
    var cell = new PdfPCell(new Phrase(i.ToString()));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    cell.VerticalAlignment = Element.ALIGN_MIDDLE;
    cell.BackgroundColor = new iTextSharp.text.BaseColor(220, 220, 220);
    cell.Border = 0;
    cell.BorderColorLeft = BaseColor.BLACK;
    cell.BorderWidthLeft = .5f;
    cell.BorderColorRight = BaseColor.BLACK;
    cell.BorderWidthRight = .5f;
    table.AddCell(cell);
}
//像平常一样创建您的名字
var表=新的PDFP表(3);
//使用属性集绑定和实例
table.TableEvent=新的TopBottomTableBorderMaker(BaseColor.BLACK,0.5f);
//其余的都一样
对于(变量i=0;i<6;i++){
var-cell=新的PdfPCell(新短语(i.ToString());
cell.HorizontalAlignment=Element.ALIGN_CENTER;
cell.VerticalAlignment=Element.ALIGN_MIDDLE;
cell.BackgroundColor=新的iTextSharp.text.BaseColor(220,220,220);
单元格边框=0;
cell.BorderColorLeft=BaseColor.BLACK;
cell.BorderWidthLeft=.5f;
cell.BorderColorRight=BaseColor.BLACK;
cell.BorderWidthRight=.5f;
表2.AddCell(cell);
}

上面我说“一般”它应该是有效的。但是,如果您有表的页眉和/或页脚,您也需要考虑这些。这应该不会太难,但您需要调整
y
值,以说明
table.HeaderRows
table.FooterRows
我遇到了相同的问题,找到了以下解决方案。 摘自“iText行动第二版” PdfPCell扩展了矩形,继承了大量方法来更改绘制边框和绘制背景的方式

“DisableBorderSide(int-Rectangle)”方法是如何在涉及任何其他大小的情况下删除边框

PdfPCell cell = new PdfPCell(new Phrase("Some Text", FontFactory.GetFont("Arial", BaseFont.WINANSI, BaseFont.EMBEDDED, 13, Font.NORMAL, BaseColor.BLACK)));
cell.BackgroundColor = new BaseColor(255, 255, 255);
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.BorderColor = BaseColor.BLACK;
cell.Border = Rectangle.BOX;
cell.BorderWidth = 1;
cell.DisableBorderSide(Rectangle.TOP_BORDER);
cell.DisableBorderSide(Rectangle.BOTTOM_BORDER);
cell.Padding = 3;
table.AddCell(cell);

我用嵌套表解决了这个问题

'CREATE TWO PDFPTABLES
 Dim tblNested1 As New PdfPTable(1)
 Dim tblNested2 As New PdfPTable(3)

 'CREATE CELLS WITH NO BORDER AND ADD THEM TO TABLE2

 Dim cellNested1 = New PdfPCell(New Phrase("CELL1"))
 cellNested1.Border = 0
 tblNested2.AddCell(cellNested1)
 Dim cellNested2 = New PdfPCell(New Phrase("CELL2"))
 cellNested2.Border = 0
 tblNested2.AddCell(cellNested2)
 Dim cellNested3 = New PdfPCell(New Phrase("CELL3"))
 cellNested3.Border = 0
 tblNested2.AddCell(cellNested3)

 'APPEND TABLE2 TO A CELL WITH DEFAULT BORDER

  Dim cell1 As New PdfPCell
  cell1.AddElement(tblNested2)

  tblNested1.AddCell(cell1)

  document.Add(tblNested1)

玛丽亚的回答最适合这种情况。Chris Hass认为他的解决方案更适合需要维护和更新的大型项目。他的解决方案是干涸的,从长远来看,这种方法更好。但如果快速和肮脏是可以的,玛丽亚的方法是完美的。这几乎是重复的。
'CREATE TWO PDFPTABLES
 Dim tblNested1 As New PdfPTable(1)
 Dim tblNested2 As New PdfPTable(3)

 'CREATE CELLS WITH NO BORDER AND ADD THEM TO TABLE2

 Dim cellNested1 = New PdfPCell(New Phrase("CELL1"))
 cellNested1.Border = 0
 tblNested2.AddCell(cellNested1)
 Dim cellNested2 = New PdfPCell(New Phrase("CELL2"))
 cellNested2.Border = 0
 tblNested2.AddCell(cellNested2)
 Dim cellNested3 = New PdfPCell(New Phrase("CELL3"))
 cellNested3.Border = 0
 tblNested2.AddCell(cellNested3)

 'APPEND TABLE2 TO A CELL WITH DEFAULT BORDER

  Dim cell1 As New PdfPCell
  cell1.AddElement(tblNested2)

  tblNested1.AddCell(cell1)

  document.Add(tblNested1)
 var Rectangular = new Rectangle(56, 621, 540,385);
                Rectangular.BorderWidthLeft = 0.1f;
                Rectangular.BorderWidthRight = 0.1f;
                Rectangular.BorderWidthTop = 0.1f;
                Rectangular.BorderWidthBottom = 0.1f;
                cb.Rectangle(Rectangular);
                cb.Stroke();