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

本文关键字:一个 单元格 设置 分割 iTextSharp | 更新日期: 2023-09-27 18:09:32

对于我的下一个问题,我必须多解释一点。: - 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 | +==========================================+

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

新答案:

如评论中所示,您可以使用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更改为89, 90, 91, 9394来测试此示例。它可以工作,但它是复杂的代码。