2016-09-26 10 views
5

C#の解答は、質問の編集部分にあります。ブルーノLowagieC# - すべてのページのitextSharp小計

から スペシャルサンクスは、私はC#でiTextSharpを経由して請求書を作成しようとしています。それは非常にうまくいくが、私はすべてのページに小計を印刷しようとしている間に問題がある。

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       |  | 
+------------------------------------------+ 

表は次のページに流れることができるAN私はフッターにページごとの小計を書くことwhant。イベント "OnEndPage"は、このイベントがテーブル内のどこにページが壊れているかを「知っていない」ため、私を助けません。

すべてのページで小計をどのように取得するか教えていただけますか?どのように私はPDFファイル上のそれを印刷するページ上の何かを合計することができます任意のソリューションですか?

私の説明がそれほど良くない場合は、申し訳ありません。私の英語に問題があります。 : -/

EDIT:

ここでは、ソリューションです。ブルーノに特別なおかげです。彼は私に道を教えてくれました。 私のバージョンでは、小計はすべてのページでリセットされません。私はこれが私の問題記述の誤解であったと思う。

新しい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'クラスを実装しています。 しかし、私は 'public override void OnEndPage(PdfWriter writer、Document doc)'で私はどこにいるのですか?テーブルは、この時点ですでに書かれています。 このイベントは 'document.Add(table);で呼び出されます –

+0

問題の説明からすぐにわからないものがいくつかあります。以下の前提が正しいとします。1.請求書文書は、複数のページにわたる可能性のある単一の大きな表で構成されます。 2.請求書はフォームではなく、文書を生成する際にすべての情報にアクセスできます。 3.現在のページのすべての商品で構成された小計と、そのページのヘッダー/フッターの現在のページまでの小計の合計を印刷します。 –

答えて

1

SubTotal例を見てみてください。

まず我々が小計と合計を追跡するクラスを作成します。私たちは、定義されている

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; 
    } 

} 

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

その後、我々は、我々は、カラム5に使用しますPdfPCellEventインタフェースを実装2つのコンストラクタ:1つは価格を含む通常のセル用です。小計を含むフッターセルの1つ(この場合は価格を渡すことはありません)。

これは、我々は、このセルのイベントを使用する方法である。結果は次のようになります

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があります。第2ページには、価格が10のアイテムに対してそれぞれ4つの本文行があります。フッターには小計40があります。余分なフッターを模倣するために余分な表を追加しました総計:500.

+0

私たちはほとんどそこにいる!どうもうありがとう!残っている問題が1つありました。たとえば、行46の高さが大きく、2ページにまたがっている場合は、ページ1の例の小計が正しくなります。しかし、2ページ目では40ではなく50になるでしょう。しかし、私はそれをブール変数を追加して修正しました。すべての読者のために:Bruno LowagieのコードはJAVA-Codeです。 C#では翻訳する必要があります。しかし、それは非常にうまくいく!驚くばかり。 :-) –

関連する問題