我想从创建的表中删除某些标题。
Table table = new Table(2).SetWidth(iText.Layout.Properties.UnitValue.CreatePercentValue(100));
Table headerTable1 = new Table(2).SetWidth(iText.Layout.Properties.UnitValue.CreatePercentValue(100));
headerTable1.AddCell(new Cell().Add(new Paragraph("Test1")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
headerTable1.AddCell(new Cell().Add(new Paragraph("Test2")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
table.AddHeaderCell(new Cell(1,2).Add(headerTable1));
Table headerTable2 = new Table(2).SetWidth(iText.Layout.Properties.UnitValue.CreatePercentValue(100));
headerTable2.AddCell(new Cell().Add(new Paragraph("Test1")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
headerTable2.AddCell(new Cell().Add(new Paragraph("Test2")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
table.AddHeaderCell(new Cell(1,2).Add(headerTable2));
Table headerTable3 = new Table(2).SetWidth(iText.Layout.Properties.UnitValue.CreatePercentValue(100));
headerTable3.AddCell(new Cell().Add(new Paragraph("Test1")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
headerTable3.AddCell(new Cell().Add(new Paragraph("Test2")).SetWidth(iText.Layout.properties.UnitValue.CreatePercentValue(50)));
table.AddHeaderCell(new Cell(1,2).Add(headerTable3));
{Add Multiple Cells to Table}
一旦表格的高度大于PageSize.A4.GetHeight()(假设我们使用的是A4内容),它将自动生成多个页面并在标题上方添加。 从第二页,我想删除headerTable2。我该怎么做?请帮我。谢谢。
答案 0 :(得分:1)
很长一段时间以来,我一直在考虑您的问题,但不幸的是,没有找到任何可行的解决方案。
在iText7中,为了覆盖某些布局元素的行为,应扩展其默认渲染器(对于表,它应为TableRenderer
),然后在一个想要设置的元素上设置此自定义渲染器的实例。过程。
一个人可以使用Table#getHeader()
元素获取表头并在其上设置一个rendere,但是存在两个不易克服的问题:
1)对于每个页面,iText都会重新创建渲染器,因此您不能假设一个渲染器实例将传播到表的溢出渲染器。要知道渲染器是否一直在使用中,当然可以引入一些静态字段,但是
2)标头的边框在父表的layout
方法中隐式处理。而且由于表的边缘情况很多,因此默认的layout
方法确实非常复杂,因此重写它是一个麻烦。不仅如此,TableRenderer
的许多字段都具有私有或默认访问权限,因此会给您带来其他麻烦。
这就是为什么我认为您必须面对这样一个事实,即不可能以您想要的方式处理表头。
但是仅标题呢? iText为客户提供IEvent
功能。可以实现一个BEGIN_PAGE(或END_PAGE)事件(在您的情况下,它是标题图),并使文档侦听它。捕获事件后,将执行绘图。
让我们看看如何实现它。
处理事件(在下面的示例中为TableHeaderEventHandler)非常简单:
TableHeaderEventHandler handler = new TableHeaderEventHandler(doc);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, handler);
这就是实现此事件的方式:
public class TableHeaderEventHandler implements IEventHandler {
protected Table table;
protected float tableHeight;
protected Document doc;
public TableHeaderEventHandler(Document doc) {
this.doc = doc;
initTable(false);
}
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
PdfPage page = docEvent.getPage();
PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
Rectangle rect = new Rectangle(pdfDoc.getDefaultPageSize().getX() + doc.getLeftMargin(),
pdfDoc.getDefaultPageSize().getTop() - doc.getTopMargin(), 523, getTableHeight());
new Canvas(canvas, pdfDoc, rect)
.add(table);
if (1 == doc.getPdfDocument().getPageNumber(page)) {
initTable(true);
}
}
public float getTableHeight() {
return tableHeight;
}
private void initTable(boolean removeTheSecondRow) {
table = new Table(3);
table.addCell("row 1, 1");
table.addCell(new Cell(1, 2).add(new Paragraph("row 1, 2 3")));
if (!removeTheSecondRow) {
table.addCell(new Cell(1, 3).add(new Paragraph("row 2, 1 2 3")));
}
table.addCell("row 3, 1");
table.addCell("row 3, 2");
table.addCell("row 3, 3");
TableRenderer renderer = (TableRenderer) table.createRendererSubTree();
renderer.setParent(new Document(new PdfDocument(new PdfWriter(new ByteArrayOutputStream()))).getRenderer());
tableHeight = renderer.layout(new LayoutContext(new LayoutArea(0, PageSize.A4))).getOccupiedArea().getBBox().getHeight();
doc.setMargins(120 + tableHeight, 36, 36, 36);
}
}
在上面的代码段中,一旦将标题放置在第一页上,我将对其进行初始化。 请注意对文档页边距的处理:您可能不希望页面的内容干扰页眉,因此需要特别注意:
TableRenderer renderer = (TableRenderer) table.createRendererSubTree();
renderer.setParent(new Document(new PdfDocument(new PdfWriter(new ByteArrayOutputStream()))).getRenderer());
tableHeight = renderer.layout(new LayoutContext(new LayoutArea(0, PageSize.A4))).getOccupiedArea().getBBox().getHeight();
doc.setMargins(120 + tableHeight, 36, 36, 36);
我一直在与您一起玩的示例可以在iText的网站或github上找到:https://github.com/itext/i7js-examples/blob/develop/src/test/java/com/itextpdf/samples/sandbox/events/TableHeader.java
但是,上述解决方案中存在一些非常明显的缺陷:
1)一个人应该自己处理border-collapsing
。
这是一个艰难的过程,一个通用的解决方案将需要大量的考虑。但是,要解决特定情况,只需以正确放置边框的方式计算空间即可。
2)应该明智地更新文档区域。
让我们看看上面的代码生成的pdf。您可能想知道为什么页眉和第二页上文档的其他元素之间存在间隙。更令人惊讶的是,为什么第三页以上没有空隙:
原因如下:处理事件时,下一页已添加到文档中。
如何克服呢?就像我在一开始所说的那样,通常会覆盖一个渲染器(这里是DocumentRenderer
)来处理它。有关更多信息,请查看以下答案:IText 7 How To Add Div or Paragraph in Header Without Overlapping Page Content?
希望会有用!
P.S。尽管答案是用Java给出的,但是用C#再现它应该没有问题,因为API完全相同。