iText 7 table 每页最后一行底部有边框

iText 7 table with border bottom on last row of each page

我正在使用 iText 7 在 PDF 文件中创建 table。 我的 table 必须只有垂直边框(每列的左侧和右侧)并且在每页的第一行也有拓扑边框 并且在每页的最后一行也是底部边框。

在每一行中,只有一列可以在两行上“跨行”(最多)。

我已经成功地创建了 table 并在每页上重复 header 但在每页的最后一行我无法绘制底部边框。

可以通过多种方式解决问题。

我使用函数 GetCell 获取一个单元格 object,然后像这样添加到 table

     var stream = new MemoryStream();
     var writer = new PdfWriter(stream);
     var pdf = new PdfDocument(writer);
     pdf.SetDefaultPageSize(PageSize.A4.Rotate());
     var document = new Document(pdf);
     iText.Layout.Element.Table table;

     ...HEADER

     table.AddHeaderCell(GetCell(1, 1, "V", dgv.Columns[i].HeaderText, "{0}", TextAlignment.CENTER, VerticalAlignment.TOP));
     ....AddHeaderCell for all columns

     ....init cycle
   
     table.AddCell(GetCell(1, 1, "F", mystring, TextAlignment.CENTER, VerticalAlignment.TOP).SetBorder(null));
     ...ending cycle
     document.Add(table);
     document.close;
     .....

然后遍历 table 中的所有单元格并将左右边框应用于单元格。

int numrows= table.GetNumberOfRows();
int numcols= table.GetNumberOfColumns();
for (int irow = 0; irow < numrows; irow++)
{
    for (int icol = 0; icol < numcols; icol++)
        {
        try 
            {
            Cell mycell = table.GetCell(irow,icol);
                mycell.SetBorderRight(new SolidBorder(0.5f));
                mycell.SetBorderLeft(new SolidBorder(0.5f));
            }
        catch (NullReferenceException)
            {
            }
        }
}

最大的困难是知道我正在写的行是否是页面上的最后一行,另一个困难是在迭代周期中获取单元格值。

注意事项:

我也可以在 GetCell 函数中应用底部边框,在这种情况下,我应该在这个阶段知道我的行是否是页面中的最后一行。我试过这个但结果不好 添加单元格后,我验证是否有足够的 space 来写另一行。

LayoutResult result = table.CreateRendererSubTree().SetParent(document.GetRenderer()).Layout(
    new LayoutContext(new LayoutArea(1, new Rectangle(0, 0, 400, 1e4f))));

LayoutArea currentArea = document.GetRenderer().GetCurrentArea();
Rectangle rectangle = currentArea.GetBBox();
float verticalPosition = rectangle.GetHeight();
float docBottom = rectangle.GetBottom();


float TableHeight = result.GetOccupiedArea().GetBBox().GetHeight();

if (verticalPosition - TableHeight <= docBottom)
{
    // document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
    //Debug.Print("........................................Last Row splitted");
};


private static Cell GetCell(int cm, int rowspan, string ItsHeader, string mytext, TextAlignment mytextalign,
    VerticalAlignment myvertalign) {
    Cell cell = new Cell(rowspan, cm);
    Paragraph p;
    if (ItsHeader == "V") {
        cell.SetBackgroundColor(iText.Kernel.Colors.ColorConstants.LIGHT_GRAY);
        cell.SetTextAlignment(mytextalign);
        p = new Paragraph(String.Format("{0}", mytext)).SetFontSize(10);
        cell.Add(p);
    } else {
        if (myvertalign == VerticalAlignment.MIDDLE) {
            Div d = new Div();
            d.SetVerticalAlignment(VerticalAlignment.MIDDLE);
            p = new Paragraph(String.Format("{0}", mytext)).SetFontSize(8);
            p.SetTextAlignment(mytextalign);
            d.Add(p);
            cell.Add(d);
        } else {
            cell.SetBackgroundColor(iText.Kernel.Colors.ColorConstants.WHITE);
            p = new Paragraph(String.Format("{0}", mytext)).SetFontSize(8);
            p.SetTextAlignment(mytextalign);
            p.SetMultipliedLeading(1.5f);
            p.SetMarginTop(0);
            cell.Add(p);
        }
    }

    return cell;
}

感谢您的时间和建议。

我会得到这样的东西 Example

这样解决了。 我结合了一些给我带来问题的事情。

  1. Table 每页重复页眉。
  2. Table 有边框。
  3. 只有左右边框的单元格
  4. 最后一页最后一行的总计
  5. 每页第一行打印 2 列值

唯一的条件是定义一个变量,用于存储页面内 table 的最大高度(对我来说是水平方向)。如果超过此高度,则会生成分页符。 谢谢你的时间。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using iText.IO.Image;
using iText.IO.Font;
using iText.IO.Font.Constants;
using iText.Kernel.Events;
using iText.Kernel.Font;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Kernel.Pdf.Xobject;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Layout;
using iText.Layout.Properties;
using iText.Layout.Renderer;
using Newtonsoft.Json;
using System.Collections.Specialized;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Web.UI.WebControls;
using System.Web;
using iText.IO.Source;


namespace PrintPDF7
{
    public class PrintPDFNew
    {
        public string Stato = "";
        private DataTable TableDati;
        private static string ID = "1472";
        private string Name = "XXXXXXX";
        private static string PathImmagine = "";
        private static Classi.DataJSON varJSON;
        private static Classi.commonParamaters parametersReceveid;

    public static string vName
    {   get { return vName; }
        set { vName = value; }
    }

    public static string vID
    {
        get { return vID; }
        set { vID = value; }
    }

    public byte[]  GetReport(HttpResponse response,  string TipoOutput, string FileToSave, GridView myGrid, Classi.commonParamaters parCommons, string appPath, string ServerMapPath)
        {
            string mystring=null;
            string fCUR = "{0:#,##0.00}";
            int columns_numbers = 18;

            PdfDocument pdf;

            Memoryms ms=null;
            PdfWriter writer;
            parametersReceveid = parCommons;

            PathImmagine = ServerMapPath + @"Images\logo.gif";

            TextAlignment vCenter = TextAlignment.CENTER;
            TextAlignment vLeft = TextAlignment.LEFT;
            TextAlignment vRight = TextAlignment.RIGHT;

            VerticalAlignment vTop = VerticalAlignment.TOP;
    
            msReader r = new msReader(ServerMapPath + "APP_DATA/DATA_INI.TXT");
            string jsonString = r.ReadToEnd();
            varJSON = JsonConvert.DeserializeObject<Classi.DataJSON>(jsonString);
            r.Close();

            parametersReceveid.ID = Convert.ToInt32(((Label)myGrid.Rows[1].Cells[1].Controls[1]).Text);
            ID = ((Label)myGrid.Rows[1].Cells[1].Controls[1]).Text;
            vName = Name;

            ms = new MemorymStream();
            writer = new PdfWriter(ms);
            pdf = new PdfDocument(writer);
            pdf.SetDefaultPageSize(PageSize.A4.Rotate());
            var document = new Document(pdf);
            iText.Layout.Element.Table table;

            table = MakeTable(columns_numberonne, pdf, document, ID, vName);
            
            TableHeaderEventHandler handler = new TableHeaderEventHandler(table,document, ID, Name);
            pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, handler);

            Footer footerHandler = new Footer();
            pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, footerHandler);

            // Calculate top margin to be sure that the table will fit the margin.
            float topMargin = 20 + handler.GetTableHeight();
            document.SetMargins(topMargin, 36, 36, 36);

            GridView dgv = myGrid;
            int dgvrowcount = dgv.Rows.Count;
            int dgvcolumncount = dgv.Columns.Count;

            MakeTableHeader(myGrid, table);

            string printID = "V";
            double Total=0; double TotalTax = 0; double TotalTax_Credit = 0;
            Cell TheCell;
            SubtotalHandler handlerTotals = new SubtotalHandler();
            float HeightTable = 0;
            float HeightHeader = 0;
            float HeightTableParz = 0;

            HeightHeader = GetHeightTable(table, document);

            for (int i = 0; i < dgvrowcount; i++)
            {
              if (float.Parse(varJSON.Height_MAX_Table) < HeightTable + HeightHeader)
                {
                HeightTableParz = HeightTable;

                BordersCells(table, "ROW","F");
                BordersCells(table, "HEADER","F");
                BordersCells(table, "FOOTER","F");
                document.Add(table);
                       
                document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
                printID = "V";
                HeightTable = 0;
                table = null;
                       
                handlerTotals = new SubtotalHandler();
                table = MakeTable(columns_numberonne, pdf, document, ID, vName);
                MakeTableHeader(myGrid, table);
                }
                else
                    {
                        printID = (i == 0 ? "V" : "F");
                    }
                
                for (int c = 0; c < dgvcolumncount; c++)
                {
                switch (dgv.Columns[c].HeaderText)
                {
                case "ID":
                    TheCell = GetCell(1, 1, "F", (printID == "V" ? ID : ""), "{0}", vCenter, vTop).SetBorder(null);
                    table.AddCell(TheCell);
                    table.AddCell(GetCell(3, 1, "F", (printID == "V" ? vName : ""), "{0}", vCenter, vTop).SetBorder(null));
                        break;
                case "Year Pag.":
                case "Year Rif.":
                case "Cause":
                        mystring = ((Label)myGrid.Rows[i].Cells[c].Controls[1]).Text;
                        table.AddCell(GetCell(1, 1, "F", mystring, "{0}", vCenter, vTop).SetBorder(null));
                    break;
                case "Desc":
                    mystring = ((Label)myGrid.Rows[i].Cells[c].Controls[1]).Text;
                    table.AddCell(GetCell(5, 1, "F", mystring, "{0}", vCenter, vTop).SetBorder(null));
                    break;
                case "Amount":
                    mystring = ((Label)myGrid.Rows[i].Cells[c].Controls[1]).Text.Replace(" €", "");
                    TheCell = GetCell(2, 1, "F", String.Format(fCUR, Convert.ToDouble(mystring)), "{0}", vCenter, vTop).SetBorder(null);
                    TheCell.SetNextRenderer(new SubtotalHandlerAwareCellRenderer(TheCell, handlerTotals, "I", Convert.ToDouble(mystring)));
                    table.AddCell(TheCell);
                    Total += Convert.ToDouble(mystring);
                    break;
                case "Tax":
                    mystring = ((Label)myGrid.Rows[i].Cells[c].Controls[1]).Text.Replace(" €", "");
                    TheCell = GetCell(2, 1, "F", String.Format(fCUR, Convert.ToDouble(mystring)), "{0}", vCenter, vTop).SetBorder(null);
                    TheCell.SetNextRenderer(new SubtotalHandlerAwareCellRenderer(TheCell, handlerTotals, "O", Convert.ToDouble(mystring)));
                    table.AddCell(TheCell);
                    TotalTax += Convert.ToDouble(mystring);
                    break;
                case "Tax_Credit":
                    mystring = ((Label)myGrid.Rows[i].Cells[c].Controls[1]).Text.Replace(" €", "");
                    TheCell = GetCell(2, 1, "F", String.Format(fCUR, Convert.ToDouble(mystring)), "{0}", vCenter, vTop).SetBorder(null);
                    TheCell.SetNextRenderer(new SubtotalHandlerAwareCellRenderer(TheCell, handlerTotals, "Tax_Credit", Convert.ToDouble(mystring)));
                    table.AddCell(TheCell);
                    TotalTax_Credit += Convert.ToDouble(mystring);
                    break;
                default:
                    break;
                    }
                }

            HeightTable = GetHeightTable(table, document) - HeightHeader - HeightTableParz;
            }
            //START WRITING TOTALS
            table.AddCell(GetCell(12, 1, "F", "Total", "{0}", vCenter, vTop).SetBorder(null));
            table.AddCell(GetCell(2, 1, "F", String.Format(fCUR, Total), "{0}", vCenter, vTop).SetBorder(null));
            table.AddCell(GetCell(2, 1, "F", String.Format(fCUR, TotalTax), "{0}", vCenter, vTop).SetBorder(null));
            table.AddCell(GetCell(2, 1, "F", String.Format(fCUR, TotalTax_Credit), "{0}", vCenter, vTop).SetBorder(null));

            //END WRITING TOTALS

            BordersCells(table, "ROW","V");
            BordersCells(table, "HEADER", "V");

            document.Add(table);

            footerHandler.WriteTotal(pdf);

            document.Close();

           byte[] content=null;
           if (TipoOutput == "RESPONSE")
               {
                    response.ContentType = varJSON.PDF_ContentType;
                    response.AddHeader("content-disposition", "attachment;filename=" + FileToSave);
                    response.Cache.SetCacheability(HttpCacheability.NoCache);
                    response.Outputms.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
               }
           else
               {
                  content = ms.ToArray();
               }

           return content;

}

        private iText.Layout.Element.Table MakeTable(int columns_numbers, PdfDocument pdf, Document doc,string ID, string Name)
        {
            iText.Layout.Element.Table table;
            table = new iText.Layout.Element.Table(UnitValue.CreatePercentArray(columns_numbers));

            table.SetWidth(MillimetersToPoints(250));
            table.SetBorder(null);
            table.SetBorderBottom(new SolidBorder(0.5f));
            table.SetBorderTop(new SolidBorder(0.5f));
            table.SetBorderLeft(new SolidBorder(0.5f));

            return table;
        }

        private void MakeTableHeader(GridView dgv, iText.Layout.Element.Table table)
        
        {
        int dgvrowcount = dgv.Rows.Count;
        int dgvcolumncount = dgv.Columns.Count;
        TextAlignment vCenter = TextAlignment.CENTER;
        VerticalAlignment vTop = VerticalAlignment.TOP;
    
        // Print The DGV Header To Table Header
        for (int i = 0; i < dgvcolumncount; i++)
        {
            switch (dgv.Columns[i].HeaderText)
            {
                case "ID":
                case "Year Pag.":
                case "Year Rif.":
                case "Cause":
                    table.AddHeaderCell(GetCell(1, 1, "V", dgv.Columns[i].HeaderText, "{0}", vCenter, vTop).SetBorderBottom(new SolidBorder(0.5f)));
                    if (dgv.Columns[i].HeaderText == "ID")
                    {
                        table.AddHeaderCell(GetCell(3, 1, "V", "Name", "{0}", vCenter, vTop).SetBorderBottom(new SolidBorder(0.5f)));
                    }
                    break;
                case "Desc.":
                    table.AddHeaderCell(GetCell(5, 1, "V", dgv.Columns[i].HeaderText, "{0}", vCenter, vTop).SetBorderBottom(new SolidBorder(0.5f)));
                    break;
                case "Amount":
                case "Tax":
                case "Tax_Credit":
                    table.AddHeaderCell(GetCell(2, 1, "V", dgv.Columns[i].HeaderText, "{0}", vCenter, vTop).SetBorderBottom(new SolidBorder(0.5f)));
                     break;
                default:
                    break;
            }
        }

     }

        private float GetHeightTable(iText.Layout.Element.Table TableDati,Document doc)
     {
            IRenderer pRenderer = TableDati.CreateRendererSubTree().SetParent(doc.GetRenderer());
            LayoutResult pLayoutResult = pRenderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4)));
            return pLayoutResult.GetOccupiedArea().GetBBox().GetHeight();

     }
   
private void BordersCells(iText.Layout.Element.Table Table, string Tipo, string BordoSuUltima)
        
{
    int rows_number =0;
    int columns_number = 0;
    bool lastrow = false;
    Cell mycell;

    switch (Tipo)
      {  case "HEADER":
              rows_number = Table.GetHeader().GetNumberOfRows();
              columns_number = Table.GetHeader().GetNumberOfColumns();
              break;
          case "ROW":
               rows_number = Table.GetNumberOfRows();
               columns_number = Table.GetNumberOfColumns();
              break;
          case "FOOTER":
              if (Table.GetFooter() !=null) 
                  {rows_number = Table.GetFooter().GetNumberOfRows();
                      columns_number = Table.GetFooter().GetNumberOfColumns();}
                      break;
          default:
              rows_number = Table.GetNumberOfRows();
              columns_number = Table.GetNumberOfColumns();
              break;
      }

    for (int irow = 0; irow < rows_number; irow++)
    {
        for (int icol = 0; icol < columns_number; icol++)
            {
            try 
                {
                    switch (Tipo)
                    {  case "HEADER":
                            mycell = Table.GetHeader().GetCell(irow, icol);
                            mycell.SetBorderBottom(new SolidBorder(0.5f));
                            break;
                    case "ROW":
                            mycell = Table.GetCell(irow,icol);
                            if (irow + 1 == rows_number)   {  lastrow = true; }
                            if (irow == 0) { mycell.SetBorderTop(new SolidBorder(0.5f)); }
                            break;
                    case "FOOTER":
                            mycell = Table.GetFooter().GetCell(irow, icol);
                            mycell.SetBorderBottom(new SolidBorder(0.5f));
                            break;
                    default:
                            mycell = Table.GetCell(irow, icol);                            
                        break;
                    }

                mycell.SetBorderRight(new SolidBorder(0.5f));
                mycell.SetBorderLeft(new SolidBorder(0.5f));

                if (mycell.GetColspan() == 12 || (lastrow == true && BordoSuUltima =="V"))
                    {mycell.SetBorderTop(new SolidBorder(0.5f));}

                }
            catch (NullReferenceException)
                {
                }
            }
    }
 }

        
private static float MillimetersToPoints(float value)
{
    return (value / 25.4f) * 72f;
}

private static Cell GetCell(int cm, int rowspan,string ItsHeader, string MyText, string myformat, TextAlignment AllineaMyText, VerticalAlignment AllineaVert)
{
    Cell cell = new Cell(rowspan, cm);
    Paragraph p;
    if (ItsHeader == "V")
        {cell.SetBackgroundColor(iText.Kernel.Colors.ColorConstants.LIGHT_GRAY);
         cell.SetTextAlignment(AllineaMyText);
         p = new Paragraph(String.Format(myformat, MyText)).SetFontSize(10);
        cell.SetBorderBottom(new SolidBorder(0.7f));
        cell.Add(p);
    }
    else
        {
         if (AllineaVert == VerticalAlignment.MIDDLE)
            {
             Div d = new Div();
             d.SetVerticalAlignment(VerticalAlignment.MIDDLE);
             p = new Paragraph(String.Format(myformat, MyText)).SetFontSize(8);
             p.SetTextAlignment(AllineaMyText);
             d.Add(p);
             cell.Add(d);
            }
            else {
            cell.SetBackgroundColor(iText.Kernel.Colors.ColorConstants.WHITE);
            p = new Paragraph(String.Format(myformat, MyText)).SetFontSize(8);
            p.SetTextAlignment(AllineaMyText);
            p.SetMultipliedLeading(1.5f);
            p.SetMarginTop(0);
            cell.Add(p);
}
 }
  return cell;
 
        
        private class TableHeaderEventHandler : IEventHandler
        {
            private iText.Layout.Element.Table table;
            private iText.Layout.Element.Table TableDati;
            private TableRenderer rendererDati;
            private float tableHeight;
            private Document doc;
            private string name;

            public TableHeaderEventHandler(iText.Layout.Element.Table tableDati, Document doc, string ID, string Name)
            {
            this.doc = doc;
            this.name = Name;
            this.TableDati = tableDati;

            InitTable(ID,Name);

            PrintPDFNew.vName = Name;

            TableRenderer renderer = (TableRenderer)table.CreateRendererSubTree();
            renderer.SetParent(new DocumentRenderer(doc));

            this.rendererDati = (TableRenderer)TableDati.CreateRendererSubTree();
            this.rendererDati.SetParent(new DocumentRenderer(doc));

        LayoutResult result = renderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4)));
                tableHeight = result.GetOccupiedArea().GetBBox().GetHeight();

            }

            public void HandleEvent(Event currentEvent)
            {
             PdfDocumentEvent docEvent = (PdfDocumentEvent)currentEvent;
             PdfDocument pdfDoc = docEvent.GetDocument();
             PdfPage page = docEvent.GetPage();
             int pageNum = pdfDoc.GetPageNumber(page);

             PdfCanvas canvas = new PdfCanvas(page.NewContentmsBefore(), page.GetResources(), pdfDoc);
             PageSize pageSize = pdfDoc.GetDefaultPageSize();
             float coordX = pageSize.GetX() + doc.GetLeftMargin();
             float coordY = pageSize.GetTop() - doc.GetTopMargin();
             float width = pageSize.GetWidth() - doc.GetRightMargin() - doc.GetLeftMargin();
             float height = GetTableHeight();
             Rectangle rect = new Rectangle(coordX, coordY, width, height);

             IRenderer pRenderer = TableDati.CreateRendererSubTree().SetParent(doc.GetRenderer());
             LayoutResult pLayoutResult = pRenderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4)));

             float y = pLayoutResult.GetOccupiedArea().GetBBox().GetY();
             float x = pLayoutResult.GetOccupiedArea().GetBBox().GetX();
             float xBottom = pLayoutResult.GetOccupiedArea().GetBBox().GetBottom();
             float xHeight = pLayoutResult.GetOccupiedArea().GetBBox().GetHeight();
             int x2 = pLayoutResult.GetOccupiedArea().GetPageNumber();

             Rectangle pagesize = page.GetPageSizeWithRotation();
             float HPage = pagesize.GetHeight();

             new Canvas(canvas, rect).Add(table).Close();
            }

            public float GetTableHeight()
            {
                return tableHeight;
            }

            private void InitTable(string ID, string Name)
            {
            table = new iText.Layout.Element.Table(UnitValue.CreatePercentArray(new float[] { 33, 33, 33 })).UseAllAvailableWidth();
            table.SetMarginBottom(5);
            table.SetMarginTop(5);
            table.SetBorder(Border.NO_BORDER);

            Cell cell = new Cell(1, 1).SetBorder(null);
            ImageData imageData = ImageDataFactory.Create(PrintPDFNew.PathImmagine);
            iText.Layout.Element.Image pdfImg = new iText.Layout.Element.Image(imageData).ScaleAbsolute(Int32.Parse(PrintPDFNew.varJSON.LOGO_LARGHEZZA), Int32.Parse(PrintPDFNew.varJSON.LOGO_Height));
            cell.Add(pdfImg);
            table.AddCell(cell);

            cell = new Cell(1, 1).SetBorder(null);
            cell.Add(new Paragraph(PrintPDFNew.varJSON.TITLE).SetFontSize(10).SetTextAlignment(TextAlignment.CENTER));
            table.AddCell(cell);

            cell = new Cell(1, 1).SetBorder(null);
            cell.Add(new Paragraph(ID + ' ' + Name).SetFontSize(10).SetTextAlignment(TextAlignment.RIGHT));
            table.AddCell(cell);

            cell = new Cell(1, 1).SetBorder(null);
            cell.Add(new Paragraph(PrintPDFNew.varJSON.Office1).SetFontSize(10).SetTextAlignment(TextAlignment.LEFT));
            table.AddCell(cell);

            table.AddCell(new Cell(1, 1).SetBorder(null).Add(new Paragraph("")));

            cell = new Cell(1, 1).SetBorder(null);
            cell.Add(new Paragraph("Period " + PrintPDFNew.parametersReceveid.Period1 + " " + PrintPDFNew.parametersReceveid.Period2 + " - Competence").SetFontSize(10).SetTextAlignment(TextAlignment.RIGHT));
            table.AddCell(cell);
            }
        }

    private class TableFooterEventHandler : IEventHandler
    {
        private iText.Layout.Element.Table table;
        private Document doc;
        private float tableHeight;

        public TableFooterEventHandler(iText.Layout.Element.Table table, Document doc, string ID, string Name)
        {
            this.table = table;
            this.doc = doc;
        }

        public void HandleEvent(Event currentEvent)
        {
         PdfDocumentEvent docEvent = (PdfDocumentEvent)currentEvent;
         PdfDocument pdfDoc = docEvent.GetDocument();
         PdfPage page = docEvent.GetPage();

         int pageNumber = pdfDoc.GetPageNumber(page);
         Rectangle pageSize = page.GetPageSize();

         TableRenderer renderer = (TableRenderer)table.CreateRendererSubTree();
         renderer.SetParent(new DocumentRenderer(doc));

         // Simulate the positioning of the renderer to find out how much space the header table will occupy.
         LayoutResult result = renderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4)));
         tableHeight = result.GetOccupiedArea().GetBBox().GetHeight();

        }
    }

    protected class Footer : IEventHandler
    {
        protected PdfFormXObject placeholder;
        protected float side = 20;
        protected float x = 800;
        protected float y = 25;
        protected float space = 4.5f;
        protected float descent = 3;

        public Footer()
        {
            placeholder = new PdfFormXObject(new Rectangle(0, 0, side, side));
        }

        public virtual void HandleEvent(Event @event)
        {
            PdfDocumentEvent docEvent = (PdfDocumentEvent)@event;
            PdfDocument pdf = docEvent.GetDocument();
            PdfPage page = docEvent.GetPage();
            int pageNumber = pdf.GetPageNumber(page);
            Rectangle pageSize = page.GetPageSize();

            PdfCanvas pdfCanvas = new PdfCanvas(page);
            Canvas canvas = new Canvas(pdfCanvas, pageSize);
            canvas.SetFontSize(9);

            Paragraph p = new Paragraph()
                .Add("Page ")
                .Add(pageNumber.ToString())
                .Add(" di");

            canvas.ShowTextAligned(p, x, y, TextAlignment.RIGHT);
            canvas.Close();

            pdfCanvas.AddXObjectAt(placeholder, x + space, y - descent);
            pdfCanvas.Release();
        }

        public void WriteTotal(PdfDocument pdfDoc)
        {
            Canvas canvas = new Canvas(placeholder, pdfDoc);
            canvas.SetFontSize(9);
            canvas.ShowTextAligned(pdfDoc.GetNumberOfPages().ToString(),
                0, descent, TextAlignment.LEFT);
            canvas.Close();
        }
    }

    private class SubtotalHandler
    {
        private double subtotalSum;
        private double subtotalTax;
        private double subTotalsTax_Credit;
        public virtual void reset(string myField)
        {
          switch (myField)
           {
             case "I":
              subtotalSum = 0; break;
             case "O":
              subtotalTax = 0; break;
             case "Tax_Credit":
               subTotalsTax_Credit = 0;  break;
             default:
               break;
            }   
        }

        public virtual void add(string myField, double val)
        {
          switch (myField)
          {
           case "I":
           subtotalSum += val; break;
           case "O":
           subtotalTax += val;break;
           case "Tax_Credit":
           subTotalsTax_Credit += val; break;
           default:
           break;
          }   
        }

        public double get(string myField)
        {
        switch (myField)
        {
        case "I":
        return subtotalSum;break;
        case "O":
        return subtotalTax;break;
        case "Tax_Credit":
        return subTotalsTax_Credit;break;
        default:
        return 0; break;
            }   
        }
    }

        private class SubtotalHandlerAwareCellRenderer : CellRenderer
        {
            private SubtotalHandler subtotalHandler;
            private double myValue;
            private string myField;
            

            public SubtotalHandlerAwareCellRenderer(Cell modelElement, SubtotalHandler subtotalHandler, string myField, double myValue)
                : base(modelElement)
            {
                this.subtotalHandler = subtotalHandler;
                this.myValue = myValue;
                this.myField = myField;
            }

            public override void Draw(DrawContext drawContext)
            {
                base.Draw(drawContext);
                subtotalHandler.add(myField, myValue);
            }

            public override IRenderer GetNextRenderer()
            {
                    return new SubtotalHandlerAwareCellRenderer((Cell)modelElement, subtotalHandler, myField, myValue);
            }
        }

        private class SubtotalCellRenderer : CellRenderer
        {
            private SubtotalHandler subtotalHandler;
            private double myValue;
            private string myField;

            public SubtotalCellRenderer(Cell modelElement, SubtotalHandler subtotalHandler,string myField)
                : base(modelElement)
            {
                this.subtotalHandler = subtotalHandler;
                this.myField = myField;
            }

            public override void Draw(DrawContext drawContext)
            {
                base.Draw(drawContext);
                (new Canvas(drawContext.GetCanvas(), drawContext.GetDocument(), occupiedArea.GetBBox())).SetFontSize(8).SetBold().ShowTextAligned(string.Format("{0:#,##0.00}", subtotalHandler.get(myField).ToString()), occupiedArea.GetBBox().GetX() + 38, occupiedArea.GetBBox().GetY() + 3, TextAlignment.CENTER);
                subtotalHandler.reset(myField);
            }

            public override IRenderer GetNextRenderer()
            {
                    return new SubtotalCellRenderer((Cell)modelElement, subtotalHandler,myField);
            }
        }
    }
}