如何使用C#中的iText7从页面顶部开始绘制长表?

问题描述 投票:0回答:1

PDF Page Example

PDF由添加到文档中的服务器段落组成,并且有一长表需要从一页的顶部(不是第一页)开始设置,这意味着一个段落将被分为两部分。

如果表很短(长度不超过页面高度),则可以通过处理起始页面的页面事件优雅地完成,只需将表添加到具有固定位置和大小的画布上,然后设置文件的上边距。

PdfDocumentEvent docEvent = (PdfDocumentEvent)currentEvent;
PdfDocument pdfDoc = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();

var currentPageNumber = pdfDoc.GetPageNumber(page);

var addingTablesOfPage = addingTables.Where(t => t.PageNumber == currentPageNumber && t.Prepared).ToList();
if (addingTablesOfPage != null && addingTablesOfPage.Count > 0)
{
    PdfCanvas canvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
    PageSize pageSize = pdfDoc.GetDefaultPageSize();

    var pageHeight = pageSize.GetHeight() - Constants.DocumentMargins[0] - Constants.DocumentMargins[2];
    var pageWidth = pageSize.GetWidth() - Constants.DocumentMargins[1] - Constants.DocumentMargins[3];

    var totalHeight = 0f;
    var alignRight = false;

    // add tables to the top of page
    foreach (var table in addingTablesOfPage.OrderBy(t => t.Type).ToList())
    {
        var tableWidth = 0f;

        float coordX = 0;
        tableWidth = pageWidth;
        coordX = pageSize.GetX() + doc.GetLeftMargin();
        totalHeight += table.TableHeight;
        float coordY = pageSize.GetTop() - Constants.DocumentMargins[0] - totalHeight;
        Rectangle rect = new Rectangle(coordX, coordY, tableWidth, table.TableHeight);

        var tableCanvas = new Canvas(canvas, rect);
        tableCanvas.Add(table.Table);
        tableCanvas.Close();
    }

    float topMargin = Constants.DocumentMargins[0] + totalHeight;

    doc.SetTopMargin(topMargin);
}
else
{
    doc.SetTopMargin(Constants.DocumentMargins[0]);
}

但是这里的表太长,将被分成多页。据我所知,Canvas类主要针对需要将元素添加到页面/ XObject上的特定预定义区域的情况,而不是针对将内容溢出到下一个区域的情况。那么我该如何实现这种行为?

谢谢!

c# itext itext7
1个回答
0
投票

关于您要实现的目标的描述非常含糊(不清楚段落是围绕表格环绕的,还是段落之间的表格;不清楚表格是否与段落中的任何文本绑定,等等) ,但我的回答应引导您朝正确的方向前进。

我将向您展示如何将适合当前页面末尾的段落部分添加到文档中,然后添加跨越多个页面的表,然后添加段落的剩余部分。

首先,我们需要为段落创建一个自定义渲染器,该渲染器将仅渲染当前适合页面的部分,并且会记住其余部分,稍后再添加。

private static class CustomParagraphRenderer extends ParagraphRenderer {
    public CustomParagraphRenderer leftover;
    private CustomParagraphRenderer toDraw;

    public CustomParagraphRenderer(Paragraph modelElement) {
        super(modelElement);
    }

    @Override
    public LayoutResult layout(LayoutContext layoutContext) {
        LayoutResult result = super.layout(layoutContext);
        if (result.getStatus() == LayoutResult.PARTIAL) {
            // Expected result here is that paragraph splits across pages
            leftover = (CustomParagraphRenderer) result.getOverflowRenderer();
            toDraw = (CustomParagraphRenderer) result.getSplitRenderer();
            return new LayoutResult(LayoutResult.FULL, result.getSplitRenderer().getOccupiedArea(), null, null);
        }
        return result;
    }

    @Override
    public void draw(DrawContext drawContext) {
        if (toDraw != null) {
            toDraw.draw(drawContext);
        } else {
            super.draw(drawContext);
        }
    }

    @Override
    public IRenderer getNextRenderer() {
        return new CustomParagraphRenderer((Paragraph) modelElement);
    }
}

现在,我们在文档中添加了一个占位符矩形,只是为了测试目的而占用一些空间,然后在我们的段落中添加了自定义渲染器(请注意,期望该段落将尽可能多地在当前页面,剩下的部分将被记住),然后添加跨多个页面的表,最后添加剩余的段落部分。

PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
Document document = new Document(pdfDocument);

document.setFontSize(20);

Div emptyArea = new Div().setHeight(400).setBackgroundColor(ColorConstants.RED);
document.add(emptyArea);

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i++) {
    sb.append(i).append(" ");
}
Paragraph p = new Paragraph(sb.toString());
p.setNextRenderer(new CustomParagraphRenderer(p).setParent(document.getRenderer()));
CustomParagraphRenderer paragraphRenderer = (CustomParagraphRenderer) p.createRendererSubTree();
// Add first part of the paragraph
document.getRenderer().addChild(paragraphRenderer);

Table table = new Table(3);
for (int i = 0; i < 25; i++) {
    for (int j = 0; j < 3; j++) {
        table.addCell(new Cell().add(new Paragraph("Cell (" + i + ", " + j + ")")));
    }
}
// Add big table
document.add(table);

// Add leftover paragraph part
document.getRenderer().addChild(paragraphRenderer.leftover.setParent(document.getRenderer()));

document.close();

结果如下所示。请注意,我故意将后续数字添加为段落内容,以便清楚地看到它是一个连续的段落,并被表格打断:

result

© www.soinside.com 2019 - 2024. All rights reserved.