iTextSharp - 仅为一个单元格/行设置Splitlate

时间:2016-09-30 07:57:34

标签: c# itext

对于我的下一个问题,我需要解释一下。 :-D

在我目前的项目中,我试图用C#创建invoice-pdf。

正如你在上一个问题中所看到的那样,想要添加小计。布鲁诺帮我成功了。在我的positionTable中的每个页脚上,由于

而添加了小计,除了最后一个小计
positionTable.SkipLastFooter = true;

在我的positionTable中可以有多头位置,所以我将表格设置为

positionTable.SplitLate = false;

现在我试图在最后一页上添加总框。为此我创建了一个额外的表(totalTable)。桌子应始终保持在一起。所以我设置了

totalTable.KeepTogether = true;

第一个问题是,如果totalTable不适合页面,它将在下一页上。但是位置表已经关闭,前一页上没有显示小计。

所以我决定将我的totalTable嵌套到我的positionTable中。我知道,我看到totalTable.KeepTogether = true不再有任何影响。

是否有将单个单元格设置为SplitLate = false;的解决方案?

+------------------------------------------+ | 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 | +==========================================+ |Sum without Tax | 90.00 | |15% Tax | 13.50 | |Total |103.50 | +==========================================+

1 个答案:

答案 0 :(得分:3)

新答案:

如评论中所示,您可以使用writeSelectedRows()添加绝对位置的所有行:

package sandbox.tables;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import sandbox.WrapToTest;

@WrapToTest
public class SubTotal3 {

    public static final String DEST = "results/tables/subtotal3.pdf";

    public static void main(String[] args) throws IOException,
            DocumentException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new SubTotal3().createPdf(DEST);
    }

    class Totals {

        double subtotal = 0;
        double total = 0;
        boolean done;
    }

    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 (totals.done) {
                PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
                ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT,
                        new Phrase(String.valueOf(totals.total)),
                        position.getLeft() + 2, position.getBottom() + 2, 0);
                totals.total = totals.total * 1.15;
                return;
            }
            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 {

        int rows = 92;
        Totals totals = new Totals();

        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        document.open();
        float width = document.right() - document.left();

        // header
        PdfPTable header = new PdfPTable(5);
        header.setWidths(new int[]{1, 1, 1, 3, 3});
        header.setTotalWidth(width);
        header.addCell("Pos");
        header.addCell("Menge");
        header.addCell("Text");
        header.addCell("Einzerpreis");
        header.addCell("Summe");
        // definitions
        PdfPTable footer = new PdfPTable(5);
        footer.setWidths(new int[]{1, 1, 1, 3, 3});
        footer.setTotalWidth(width);
        PdfPCell cell = new PdfPCell(new Phrase("Subtotal"));
        cell.setColspan(4);
        footer.addCell(cell);
        cell = new PdfPCell();
        cell.setCellEvent(new SubTotal3.SubTotalEvent(totals));
        footer.addCell(cell);

        // actual table
        PdfPTable table = new PdfPTable(5);
        table.setWidths(new int[]{1, 1, 1, 3, 3});
        table.setTotalWidth(width);
        // table body
        for (int r = 0; r < rows;) {
            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);
        }

        // extra footer
        PdfPTable total = new PdfPTable(5);
        total.setWidths(new int[]{1, 1, 1, 3, 3});
        total.setTotalWidth(width);
        cell = new PdfPCell(new Phrase("Total (excl. vat)"));
        cell.setColspan(4);
        total.addCell(cell);
        cell = new PdfPCell();
        cell.setCellEvent(new SubTotal3.SubTotalEvent(totals));
        total.addCell(cell);
        cell = new PdfPCell(new Phrase("VAT"));
        cell.setColspan(4);
        total.addCell(cell);
        total.addCell("15%");
        cell = new PdfPCell(new Phrase("Total (incl. vat)"));
        cell.setColspan(4);
        total.addCell(cell);
        cell = new PdfPCell();
        cell.setCellEvent(new SubTotal3.SubTotalEvent(totals));
        total.addCell(cell);

        PdfContentByte cb = writer.getDirectContent();
        float availableHeight = document.top() - document.bottom()
            - footer.getTotalHeight() - footer.getTotalHeight();
        int start = 0;
        float left = document.left();
        float pos = document.top();
        for (int i = 0; i < rows; ) {
            pos = header.writeSelectedRows(0, -1, left, pos, cb);
            float height = 0;
            while (height < availableHeight && i < rows) {
                height += table.getRowHeight(i++);
            }
            if (height >= availableHeight) i--;
            pos = table.writeSelectedRows(start, i, left, pos, cb);
            start = i;
            height += total.getTotalHeight();
            if (i == rows) {
                if (height > availableHeight) {
                    footer.writeSelectedRows(0, -1, left, pos, cb);
                    document.newPage();
                    pos = document.top();
                }
                totals.done = true;
                total.writeSelectedRows(0, -1, left, pos, cb);
            }
            else {
                footer.writeSelectedRows(0, -1, left, pos, cb);
                document.newPage();
                pos = document.top();
            }
        }

        document.close();
    }
}

上一个回答:

这是我最终得到的代码。我分享它的价值:

package sandbox.tables;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class SubTotal2 {

    public static final String DEST = "results/tables/subtotal2.pdf";

    public static void main(String[] args) throws IOException,
            DocumentException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new SubTotal2().createPdf(DEST);
    }

    class Totals {

        double subtotal = 0;
        double total = 0;
    }

    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 writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        document.open();
        // actual table
        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");
        // definitions
        table.setHeaderRows(1);
        table.setComplete(false);
        PdfPCell cell;
        float threshold = 55;
        // table body
        for (int r = 0; r < 92;) {
            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);
            if (writer.getVerticalPosition(false) < threshold) {
                cell = new PdfPCell(new Phrase("Subtotal"));
                cell.setColspan(4);
                table.addCell(cell);
                cell = new PdfPCell();
                cell.setCellEvent(new SubTotal2.SubTotalEvent(totals));
                table.addCell(cell);
            }
        }
        // extra footer
        PdfPTable tTable = new PdfPTable(5);
        tTable.setKeepTogether(true);
        tTable.setWidths(new int[]{1, 1, 1, 3, 3});
        cell = new PdfPCell(new Phrase("Total (excl. vat)"));
        cell.setColspan(4);
        tTable.addCell(cell);
        tTable.addCell(String.valueOf(totals.total));
        cell = new PdfPCell(new Phrase("VAT"));
        cell.setColspan(4);
        tTable.addCell(cell);
        tTable.addCell("15%");
        cell = new PdfPCell(new Phrase("Total (incl. vat)"));
        cell.setColspan(4);
        tTable.addCell(cell);
        tTable.addCell(String.valueOf(totals.total * 1.15));
        tTable.setTotalWidth(table.getTotalWidth());
        if (
            writer.getVerticalPosition(false) >= threshold &&
            writer.getVerticalPosition(false) < document.bottom() + tTable.getTotalHeight()) {
            cell = new PdfPCell(new Phrase("Subtotal"));
            cell.setColspan(4);
            table.addCell(cell);
            cell = new PdfPCell();
            cell.setCellEvent(new SubTotal2.SubTotalEvent(totals));
            table.addCell(cell);
        }
        table.setComplete(true);
        document.add(table);
        document.add(tTable);
        document.close();
    }
}

此代码中有一些黑暗魔法:threshold的值是经过反复试验确定的。它是一个Y位置,定义我们在哪个Y位置决定需要一个页脚。这不是一个完整的猜测:您可以获取底部边距的Y位置(36),添加单行的高度(16)并添加足够的空间,确保不超过您添加的底部边距两行的高度。

不要定义页脚,只需逐行添加表格,并检查每一行后的Y位置。如果达到阈值(writer.getVerticalPosition(false) < threshold),请添加页脚。

现在我们每次接近页面末尾时都会添加页脚,但如果我们不接近底部边距,则不会添加页脚,但是足够接近以便需要新页面包含总计的表(writer.getVerticalPosition(false) >= threshold && writer.getVerticalPosition(false) < document.bottom() + tTable.getTotalHeight())。在这种情况下,我们还需要添加额外的页脚行。

您可以通过将值92更改为8990919394来测试此示例。它有效,但它是棘手的代码。