使用 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;
}
修改后的样式
还有个小问题,就是该方法会导致文字被分割,待解决。。。