【问题标题】:Itextsharp PDFPTable how to make a border around entire tableItextsharp PDFPTable 如何在整个表格周围制作边框
【发布时间】:2014-08-23 18:37:46
【问题描述】:

我正在使用 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); 

问题显然是我无法检测到最后一行添加边框底部,但我想必须有一种方法来控制“表格”本身的边框,或者我采取了错误的方法到这个?

【问题讨论】:

    标签: c# itext


    【解决方案1】:

    正如您所发现的,PdfPTable 没有边框,可能是因为 PDF 首先没有表格。将边框直接放在PdfPCell 上可能更有意义(即使PDF 也不支持这些)。无论如何,表格只是单元格的集合,所以让他们处理吧。

    无论如何,解决方案是在PdfPTable 类的实例上设置TableEvent。为此,您需要自定义实现 IPdfPTableEvent 接口。以下代码通常应该为您执行此操作(请参阅底部的“一般”注释)

    class TopBottomTableBorderMaker : IPdfPTableEvent {
        private BaseColor _borderColor;
        private float _borderWidth;
    
        /// <summary>
        /// Add a top and bottom border to the table.
        /// </summary>
        /// <param name="borderColor">The color of the border.</param>
        /// <param name="borderWidth">The width of the border</param>
        public TopBottomTableBorderMaker(BaseColor borderColor, float borderWidth ) {
            this._borderColor = borderColor;
            this._borderWidth = borderWidth;
        }
        public void TableLayout(PdfPTable table, float[][] widths, float[] heights, int headerRows, int rowStart, PdfContentByte[] canvases) {
            //widths (should be thought of as x's) is an array of arrays, first index is for each row, second index is for each column
            //The below uses first and last to calculate where each X should start and end
            var firstRowWidths = widths[0];
            var lastRowWidths = widths[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;
    
            //heights (should be thought of as y's) is the y for each row's top plus one extra for the last row's bottom
            //The below uses first and last to calculate where each Y should start and end
            var firstRowYStart = heights[0];
            var firstRowYEnd = heights[1] - firstRowYStart;
    
            var lastRowYStart = heights[heights.Length - 1];
            var lastRowYEnd = heights[heights.Length - 2] - lastRowYStart;
    
            //Where we're going to draw our lines
            PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
    
            //I always try to save the previous state before changinge anything
            canvas.SaveState();
    
            //Set our line properties
            canvas.SetLineWidth(this._borderWidth);
            canvas.SetColorStroke(this._borderColor);
    
            //Draw some rectangles
            canvas.Rectangle(
                            firstRowXStart,
                            firstRowYStart,
                            firstRowXEnd,
                            firstRowYEnd
                            );
            //They aren't actually drawn until you stroke them!
            canvas.Stroke();
    
            canvas.Rectangle(
                            lastRowXStart,
                            lastRowYStart,
                            lastRowXEnd,
                            lastRowYEnd
                            );
            canvas.Stroke();
    
            //Restore any previous settings
            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);
    }
    

    上面我说“通常”它应该可以工作。但是,如果您有表格页眉和/或页脚,您也需要将这些考虑在内。这应该不会太难,但您需要调整 y 的值以考虑 table.HeaderRowstable.FooterRows

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,找到了以下解决方案。 来自“iText In Action 第二版” PdfPCell 扩展了 Rectangle,继承了大量的方法来改变绘制边框和绘制背景的方式..

      “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);
      

      【讨论】:

        【解决方案3】:

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

        '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 的观点,他的解决方案更适合需要维护和更新的大型项目。他的解决方案是一个 DRY 的解决方案,而且从长远来看,这种方法更好。但如果快速和肮脏是可以的,他们玛丽亚的方法是完美的。
        【解决方案4】:
         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();
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-06
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多