解决xhtmlrenderer flying-saucer-pdf-itext5 生成pdf时html中table分页内容太多挤到第二页问题。

使用 flying-saucer-pdf-itext5 生成pdf时html中table的行如果太高的话会被挤到第二页展示,导致第一页中空白一大块。

 

 

解决办法:

修改org.xhtmlrenderer.render.Box 类的 forcePageBreakBefore 方法。

public int forcePageBreakBefore(LayoutContext c, IdentValue pageBreakValue, boolean pendingPageName) {
        PageBox page = c.getRootLayer().getFirstPage(c, this);
        if (page == null) {
            XRLog.layout(Level.WARNING, "Box has no page");
            return 0;
        } else {
            // 纯文本类型标签不做分页时的分割
            if (this instanceof LineBox) {
                return 0;
            }
            Element element = this.getElement();
            if (element != null) {
                if (element.getTagName().equalsIgnoreCase("p") || element.getTagName().equalsIgnoreCase("span")) {
                    return 0;
                } else if (element.getTagName().equalsIgnoreCase("div")) {
                    boolean flag = true;
                    NodeList childNodes = element.getChildNodes();
                    int length = childNodes.getLength();
                    for (int i = 0; i < length; i++) {
                        Node item = childNodes.item(i);
                        // 如果整个元素内全是文本内容则不进行分割,有一个元素是非文本类的则进行分割
                        if (!item.getNodeName().equalsIgnoreCase("#text") && !item.getNodeName().equalsIgnoreCase("p") && !item.getNodeName().equalsIgnoreCase("span")) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        return 0;
                    }
                }
            }

            int pageBreakCount = 1;
            if (page.getTop() == getAbsY()) {
                pageBreakCount--;
                if (pendingPageName && page == c.getRootLayer().getLastPage()) {
                    c.getRootLayer().removeLastPage();
                    c.setPageName(c.getPendingPageName());
                    c.getRootLayer().addPage(c);
                }
            }
            if ((page.isLeftPage() && pageBreakValue == IdentValue.LEFT) ||
                    (page.isRightPage() && pageBreakValue == IdentValue.RIGHT)) {
                pageBreakCount++;
            }

            if (pageBreakCount == 0) {
                return 0;
            }

            if (pageBreakCount == 1 && pendingPageName) {
                c.setPageName(c.getPendingPageName());
            }

            int delta = page.getBottom() + c.getExtraSpaceTop() - getAbsY();
            if (page == c.getRootLayer().getLastPage()) {
                c.getRootLayer().addPage(c);
            }

            if (pageBreakCount == 2) {
                page = (PageBox) c.getRootLayer().getPages().get(page.getPageNo() + 1);
                delta += page.getContentHeight(c);

                if (pageBreakCount == 2 && pendingPageName) {
                    c.setPageName(c.getPendingPageName());
                }

                if (page == c.getRootLayer().getLastPage()) {
                    c.getRootLayer().addPage(c);
                }
            }

            setY(getY() + delta);

            return delta;
        }
    }

再将其子类 TableRowBox 中的 forcePageBreakBefore 方法内容注释掉。

public int forcePageBreakBefore(LayoutContext c, IdentValue pageBreakValue,
                                    boolean pendingPageName) {
       /* int currentDelta = super.forcePageBreakBefore(c, pageBreakValue, pendingPageName);

        // additional calculations for collapsed borders.
        if (c.isPrint() && getStyle().isCollapseBorders()) {
            // get destination page for this row
            PageBox page = c.getRootLayer().getPage(c, getAbsY() + currentDelta);
            if (page!=null) {

                // calculate max spill from the collapsed top borders of each child
                int spill = 0;
                for (Iterator i = getChildIterator(); i.hasNext(); ) {
                    TableCellBox cell = (TableCellBox)i.next();
                    BorderPropertySet collapsed = cell.getCollapsedPaintingBorder();
                    if (collapsed != null) {
                        spill = Math.max(spill, (int)collapsed.top() / 2);
                    }
                }

                // be sure that the current start of the row is >= the start of the page
                int borderTop = getAbsY() + currentDelta + (int)getMargin(c).top() - spill;
                int rowDelta = page.getTop() - borderTop;
                if (rowDelta > 0) {
                    setY(getY() + rowDelta);
                    currentDelta += rowDelta;
                }
            }
        }
        return currentDelta;*/
        return 0;
    }

修改后的样式

 

还有个小问题,就是该方法会导致文字被分割,待解决。。。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
flying-saucer-pdf是一个Java库,用于将HTML文档转换为PDF格式。它提供了一种简单的方式来生成高质量的PDF文件,可以用于生成报告、电子书、发票等各种类型的文档。 使用flying-saucer-pdf可以通过以下步骤来下载PDF工具类: 1. 首先,你需要在你的项目添加flying-saucer-pdf的依赖。你可以在Maven或Gradle添加以下依赖: Maven: ```xml <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.22</version> </dependency> ``` Gradle: ```groovy implementation 'org.xhtmlrenderer:flying-saucer-pdf:9.1.22' ``` 2. 下载完成后,你可以使用flying-saucer-pdf提供的API来生成PDF文件。首先,你需要创建一个`ITextRenderer`对象,然后将HTML内容加载到该对象,并使用`createPDF()`方法将其转换为PDF文件。以下是一个简单的示例代码: ```java import org.xhtmlrenderer.pdf.ITextRenderer; public class PdfGenerator { public static void main(String[] args) throws Exception { String htmlContent = "<html><body><h1>Hello, World!</h1></body></html>"; ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(htmlContent); renderer.layout(); String outputFile = "output.pdf"; renderer.createPDF(new FileOutputStream(outputFile)); System.out.println("PDF generated successfully!"); } } ``` 以上代码将生成一个包含"Hello, World!"标题的PDF文件,并将其保存为output.pdf。 希望这个简单的介绍能帮助到你!如果你有任何进一步的问题,请随提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值