2016-09-26 51 views
5

C#的解決方案可以在問題的Edit-Part中找到。 特別感謝布魯諾LowagieC# - 每頁上的itextSharp小計

我試圖通過建立在iTextSharp的C#的發票。它工作得很好,但即時通報問題,而我試圖在每個頁面上打印小計。

下面是使用創建表的產品代碼IM的一部分:

PdfPTable table = new PdfPTable(5); 
     table.WidthPercentage = 100; 
     float[] widths = new float[] { 10f, 30f, 120f, 30f, 30f }; 
     table.SetWidths(widths); 
     table.SkipLastFooter = true; 
     table.SpacingAfter = 10;      

     //Cells to Write Header & Footer 
     AddCell(table, "Pos.", PdfPCell.ALIGN_RIGHT, BORDER_LTB, 0); 
     AddCell(table, "Menge", PdfPCell.ALIGN_RIGHT, BORDER_TB); 
     AddCell(table, "Text", PdfPCell.ALIGN_LEFT, BORDER_TB); 
     AddCell(table, "Einzelpreis ", PdfPCell.ALIGN_RIGHT, BORDER_TB); 
     AddCell(table, "Summe", PdfPCell.ALIGN_RIGHT, BORDER_RTB); 

     AddCell(table, "SUBTOTAL", PdfPCell.ALIGN_LEFT, BORDER_LTB, 7, 4); 
     AddCell(table, "", PdfPCell.ALIGN_LEFT, BORDER_RTB); 

     table.HeaderRows = 2; 
     table.FooterRows = 1; 

     //Cells with positions of invoice 
     for (int i = 0; i < beleg.Einzel.Count; i++) 
     { 
      AddCell(table, beleg.Einzel[i].be_lfd_nr.ToString(), PdfPCell.ALIGN_LEFT, BORDER_LTB); 
      AddCell(table, beleg.Einzel[i].be_art_menge.ToString("N", _gbVars.NFI3D), PdfPCell.ALIGN_RIGHT, BORDER_TB); 
      AddCell(table, (beleg.Einzel[i].be_art_bez.ToString() + "\n" + beleg.Einzel[i].be_pos_text.ToString()).Trim(), PdfPCell.ALIGN_LEFT, BORDER_TB); 
      AddCell(table, beleg.Einzel[i].be_summe_preis.ToString("N", _gbVars.NFI2D), PdfPCell.ALIGN_RIGHT, BORDER_TB); 
      AddCell(table, beleg.Einzel[i].be_summe_netto.ToString("N", _gbVars.NFI2D), PdfPCell.ALIGN_RIGHT, BORDER_RTB); 
     } 

     table.SplitLate = false; 
     document.Add(table); 

Border_RTB等都是我的邊框樣式常量。

此代碼生成一個表女巫看起來是這樣的:

+------------------------------------------+ 
| Pos | Menge | Text | Einzelpreis | Summe | 
+------------------------------------------+ 
| 1 | 2 | Text |  10.00 | 20.00 | 
+------------------------------------------+ 
| 2 | 1 | Text |  10.00 | 10.00 | 
+------------------------------------------+ 
| 3 | 4 | Text |  10.00 | 40.00 | 
+------------------------------------------+ 
| 4 | 2 | Text |  10.00 | 20.00 | 
+------------------------------------------+ 
|SUBTOTAL       |  | 
+------------------------------------------+ 

表可以流動到下一頁的我whant在頁腳寫在每一頁的小計。事件「OnEndPage」不能幫助我,因爲這個事件不會「知道」表中頁面被破壞的位置。

有人能告訴我如何在每個頁面上獲得小計嗎?有沒有什麼解決方案,我可以總結一個頁面上的東西打印出來的pdf文件?

對不起,如果我的描述不是很好。我的英語有問題。 : -/

編輯:

這裏是解決方案。特別感謝布魯諾。他給我指明瞭方向。 在我的版本中,小計不會在每頁上重置。我想這是我對這個問題的描述中的一個錯誤。

新Clases:

public class Totals 
    { 
     public double subtotal = 0; 
     public double total = 0; 
    } 


    public class SubTotalEvent : IPdfPCellEvent 
    { 
     Double price; 
     Totals totals; 
     bool printTotals = false;  //If we just whant to print out the Subtotal, this will be true. 
     bool CellWrittenOnce = false; //Bool to SUM price just once (if row flows to a second page) 

     public SubTotalEvent(Totals totals, double price) { 
      printTotals = false; 
      this.totals = totals; 
      this.price = price; 
     } 

     public SubTotalEvent(Totals totals) { 
      this.totals = totals; 
      printTotals = true; 
     } 

     public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) { 
      if (printTotals) 
      { 
       PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS]; 
       ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(totals.subtotal.ToString()), position.GetLeft(0) + 2, position.GetBottom(0) + 2, 0); 
       return; 
      }  
      if (!CellWrittenOnce) { 
       totals.subtotal += price; 
       totals.total += price; 
      } 
      CellWrittenOnce = true; 
     } 
    } 

代碼來創建表:

PdfPTable table = new PdfPTable(5); 
     table.WidthPercentage = 100; 
     float[] widths = new float[] { 10f, 30f, 120f, 30f, 30f }; 
     table.SetWidths(widths); 
     table.SkipLastFooter = true; 
     table.SpacingAfter = 10;      

     AddCell(new PdfPCell(new Phrase("item"))); 
     AddCell(new PdfPCell(new Phrase("amount"))); 
     AddCell(new PdfPCell(new Phrase("text"))); 
     AddCell(new PdfPCell(new Phrase("price"))); 
     AddCell(new PdfPCell(new Phrase("sum"))); 

     Totals totals = new Totals(); 
     PdfPCell cel = new PdfPCell(new Phrase("Subtotal")); 
     cel.Colspan = 4; 
     table.AddCell(cel); 
     cel = new PdfPCell(); 
     cel.CellEvent = new SubTotalEvent(totals); 
     table.AddCell(cel); 


     table.HeaderRows = 2; 
     table.FooterRows = 1; 

     for (int i = 0; i < beleg.Einzel.Count; i++) 
     { 
      AddCell(new PdfPCell(new Phrase(i.toString()))); 
      AddCell(new PdfPCell(new Phrase("2"))); 
      AddCell(new PdfPCell(new Phrase("ItemText"))); 
      AddCell(new PdfPCell(new Phrase("10.00"))); 

      cell = new PdfPCell(new Phrase("20.00")); 
      cell.CellEvent = new SubTotalEvent(totals, 20.00); 
      table.AddCell(cell); 
     } 

     table.SplitLate = false; 
     document.Add(table); 
+2

您需要實現'PdfPageEventHelper'類。每次創建頁面時都會執行您的實現。請參閱本教程以瞭解如何實現它。http://www.mazsoft.com/blog/post/2008/04/30/Code-sample-for-using-iTextSharp-PDF-library – Darren

+1

我實現了'PdfPageEventHelper'類。 但我怎麼能找出'公共覆蓋無效OnEndPage(PdfWriter作家,文檔doc)'我在表中?該表已經寫在這一點上。 這個事件在'document.Add(table);' –

+0

處調用,有些事情我的問題描述中沒有立即明白,所以我不確定我是否有答案。以下假設是否正確:1.您的發票文檔由可能跨越多個頁面的單個大表組成。 2.您的發票不是表格,您可以在生成文檔時訪問所有信息。 3.您希望打印由當前頁面上的所有產品組成的小計+小計總和,直到該頁面頁眉/頁腳中的當前頁面。 –

回答

1

請大家看看SubTotal例子。

首先,我們創建一個類來跟蹤小計和總計:

class Totals { 
    double subtotal = 0; 
    double total = 0; 
} 

然後我們實現PdfPCellEvent接口,我們將在5列中使用:

class SubTotalEvent implements PdfPCellEvent { 

    Double price; 
    Totals totals; 

    public SubTotalEvent(Totals totals, double price) { 
     this.totals = totals; 
     this.price = price; 
    } 

    public SubTotalEvent(Totals totals) { 
     this.totals = totals; 
     price = null; 
    } 

    @Override 
    public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) { 
     if (price == null) { 
      PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS]; 
      ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, 
        new Phrase(String.valueOf(totals.subtotal)), 
        position.getLeft() + 2, position.getBottom() + 2, 0); 
      totals.subtotal = 0; 
      return; 
     } 
     totals.subtotal += price; 
     totals.total += price; 
    } 

} 

我們定義兩個構造函數:一個用於包含價格的正常單元格。一個用於包含小計的頁腳單元格(在這種情況下,我們不會傳遞價格)。

這是我們如何使用這個方格事件:

public void createPdf(String dest) throws IOException, DocumentException { 

    Totals totals = new Totals(); 

    Document document = new Document(); 
    PdfWriter.getInstance(document, new FileOutputStream(dest)); 
    document.open(); 
    PdfPTable table = new PdfPTable(5); 
    table.setWidths(new int[]{1, 1, 1, 3, 3}); 
    // header 
    table.addCell("Pos"); 
    table.addCell("Menge"); 
    table.addCell("Text"); 
    table.addCell("Einzerpreis"); 
    table.addCell("Summe"); 
    // footer 
    PdfPCell cell = new PdfPCell(new Phrase("Subtotal")); 
    cell.setColspan(4); 
    table.addCell(cell); 
    cell = new PdfPCell(); 
    cell.setCellEvent(new SubTotalEvent(totals)); 
    table.addCell(cell); 
    // definitions 
    table.setHeaderRows(2); 
    table.setFooterRows(1); 
    // table body 
    for(int r = 0; r < 50;){ 
     table.addCell(String.valueOf(++r)); 
     table.addCell("1"); 
     table.addCell("text"); 
     table.addCell("10.0"); 
     cell = new PdfPCell(new Phrase("10.0")); 
     cell.setCellEvent(new SubTotalEvent(totals, 10)); 
     table.addCell(cell); 
    } 
    document.add(table); 
    // extra footer 
    table = new PdfPTable(5); 
    table.setWidths(new int[]{1, 1, 1, 3, 3}); 
    cell = new PdfPCell(new Phrase("Grand total")); 
    cell.setColspan(4); 
    table.addCell(cell); 
    table.addCell(String.valueOf(totals.total)); 
    document.add(table); 
    document.close(); 
} 

結果看起來是這樣的:

enter image description here

在第一頁上,我們有46的身體行,每行與項目價格10。在頁腳中,我們有一個小計460.在第二頁,我們有4個正文行,每個價格爲10的商品。在頁腳中,我們有一個小計40.我們添加了一個額外的表來模仿額外的頁腳總計:500.

+0

我們快到了!非常感謝!還剩下一個問題:例如,如果第46行的高度更高並且流過兩頁,則第1頁上示例中的小計將是正確的。但在第二頁,它會是50,而不是40.但我修復了一個額外的bool變量。對於所有讀者:上面的代碼來自Bruno Lowagie是JAVA代碼。對於C#你必須翻譯。但它工作得很好!真棒。 :-) –