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 |
+==========================================+
新答案:
如评论中所示,您可以使用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
, 93
和94
来测试此示例。它可以工作,但它是复杂的代码。