欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > poi-tl、aspose实现word中表在每页携带表头表尾

poi-tl、aspose实现word中表在每页携带表头表尾

2024/10/24 12:27:36 来源:https://blog.csdn.net/i_am_love_CrCr/article/details/140291689  浏览:    关键词:poi-tl、aspose实现word中表在每页携带表头表尾

实现word中表在每页携带表头表尾(第一版)

word中的表格如果只有一页时表头表尾都很好处理,当中间内容足够多时,表尾只会出现在最后一页,表头也只会出现在第一页,之前想过用word自带的页眉页尾来处理但是,效果不尽人意!因为内容与页眉页尾有一定的间隔,有一种割裂感!
在这里插入图片描述
如上图,就是使用页眉页尾的方法解决的,一般场景时够用了!程序员都是有些追求的,不能尽善尽美也要尽可能的完美,接下来是用aspse实现的无缝隙的完美版。

准备工作

需要项目引入aspose(支持正版)不会引入的自己去查maven本地加载jar包
然后接下来咱们要了解一下aspose的概念
aspose中虽然 页 操作很少,但是每一个元素的Y坐标都是按照页来的 咱们可以根据这个来判断是第几页了
每一页刚开头的元素Y值一定小于上一页最后一个元素的Y值

//以双精度返回框架矩形左上角的Y坐标。double Y = enumerator.getRectangle().getY();

要注意的是咱们要获取到word表的实际高度,后面有具体代码

实现过程

进行处理,分为三个阶段,我的注解给的很详细,再不懂的就留言吧!
第一为首页数据进行排序处理
第二处理除首尾两页的数据
第三处理最后一页的数据

/*** aspose实现复制行* 没有页的概念 需要手动算总行高 (页面大小包括了 页眉页尾)* 演示测试方法,表头为6行 表尾为4行* @throws Exception*/@Testvoid asposeTableCopyRow() throws Exception {Document doc = new Document("testEndAddOutOnePage.docx");Table table = (Table) doc.getChild(NodeType.TABLE, 1, true);double tableHeadHeight = getTableHeadHeight(doc, 6);//表头double tableTailHeight = getTableTailHeight(doc, 4);//表尾double tableHeightMax = getTableHeightMax(doc, 6);//word中table适配的最高高度if (tableHeightMax == 0.0){//需要处理的word文件不足一页 直接返回原文件return;}double tableCommonRowHeight = getTableCommonRowHeight(doc, 6, 4);//获取自匹配插入数据的大众行高int commonRow = 0;//获取自匹配插入数据的大众行的代表行索引int numRows = 0;//最后一页补充条数LayoutCollector collector = new LayoutCollector(doc);//获取实际行高int pages = 1;//标记是不是第一页double sumHeight = 0;//手动记录总行高int count = table.getRows().getCount();//总行数for (int row = 0 ; row < count - 4 ; row++) {//循环跳过表尾double height = findRowHeight(collector, row, table, doc);//以双精度返回框架矩形的高度if (pages == 1){//第一页开始写入数据if (height == tableCommonRowHeight && commonRow == 0){commonRow = row; //此时的row还未row++ 就是具体行的索引}sumHeight = sumHeight + height;if (tableHeightMax - sumHeight - tableTailHeight < 0){//该页已经满了如果加上次行后表尾位置不够 判断为不能插入到此页 调整上 一行 样式进行适配double proRowHeight = findRowHeight(collector, row - 1, table, doc);//获取到上行的行高table.getRows().get(row-1).getRowFormat().setHeight(proRowHeight + (tableHeightMax - sumHeight - tableTailHeight) + height);for (int i = 0; i < 4; i++) {Node node = table.getRows().get(table.getRows().getCount() - 4 + i).deepClone(true);table.getRows().insert(row ,node);//插入到第几行上方 因为刚刚说明过是多加了 所以这里把表尾加到此行上方是正确的row++;//插入航后 指针也要相应的向下移动count++;//总行数也跟着增加}sumHeight = height;//表尾没有空间将这行放下 所以需要放在下一页pages++;}}else { //不是首页多了一个表头sumHeight = sumHeight + height;if (tableHeightMax - sumHeight - tableHeadHeight - tableTailHeight < 0){//该页已经满了如果加上次行后表尾位置不够 判断为不能插入到此页 调整上一行样式进行适配double proRowHeight = findRowHeight(collector, row - 1, table, doc);//获取到上行的行高table.getRows().get(row-1).getRowFormat().setHeight(proRowHeight + (tableHeightMax - sumHeight - tableHeadHeight - tableTailHeight) + height);for (int i = 0; i < 4; i++) {Node node = table.getRows().get(table.getRows().getCount() - 4 + i).deepClone(true);table.getRows().insert(row ,node);row++;count++;}sumHeight = height;//表尾没有空间将这行放下 所以需要放在下一页pages++;}}}//上面的for循环结束后就是到最后一页的处理逻辑if (pages == 1){//可能信息很少第一页都没装满//如果只有一页 直接返回原文件}else {double residuePlace = tableHeightMax - sumHeight - tableHeadHeight - tableTailHeight;//最后一页剩余空间numRows = (int) (residuePlace/tableCommonRowHeight);//向下取整 看最多还能插入几条数据for (int i = 0; i < numRows; i++) {Node node = table.getRows().get(commonRow).deepClone(true);table.getRows().insert(count- 4,node);//因为索引是从0开始的 行数是从1开始 insert函数是在此行的上方插入所以这里可以正好抵消count++;sumHeight = sumHeight + tableCommonRowHeight;//由于插入的新行是复制的大众行 这个行高是已知的}table.getRows().get(count - 5).getRowFormat().setHeight(tableCommonRowHeight + (tableHeightMax - sumHeight - tableHeadHeight - tableTailHeight));//因为是向上取整获得的行数 所以很可能会有一段留白这里补上}clearLastRowData(numRows, table, doc);//清除最后一页补充的信息collector.clear();doc.updatePageLayout();doc.save("xxx_new.docx");}
		double tableHeadHeight = getTableHeadHeight(doc, 6);//表头double tableTailHeight = getTableTailHeight(doc, 4);//表尾double tableHeightMax = getTableHeightMax(doc, 6);//word中table适配的最高高度if (tableHeightMax == 0.0){//需要处理的word文件不足一页 直接返回原文件return;}double tableCommonRowHeight = getTableCommonRowHeight(doc, 6, 4);//获取自匹配插入数据的大众行高

这部分数据是根据你们需要使用的数据进行个性化处理的。
如果需要这部分代码等我有空了,去除敏感信息后把代码附上·······

该方法使用到的方法如下

获取实际行高:

//获取实际行高double findRowHeight(LayoutCollector collector, int row, Table table, Document doc) throws Exception {//获取实际行高LayoutEnumerator enumerator = new LayoutEnumerator(doc);enumerator.setCurrent(collector.getEntity(table.getRows().get(row).getFirstCell().getFirstParagraph()));//在每一层中寻找row类型的实际参数while (enumerator.getType()!= LayoutEntityType.ROW) {enumerator.moveParent();}//以双精度返回框架矩形的高度。return enumerator.getRectangle().getHeight();}

多余行内容清除:

void clearLastRowData(int numRows, Table table, Document doc){for (int i = 0; i < numRows; i++) {for (Cell cell : table.getRows().get(table.getRows().getCount() - 5 - i)) {//将单元格中的第一个段落移除cell.getFirstParagraph().remove();//新建一个段落Paragraph p = new Paragraph(doc);//设置一个string的值String value = " ";//把设置的值赋给之前新建的段落p.appendChild(new Run(doc, value));//将此段落加到单元格内cell.appendChild(p);}}}

遇到的困难:

之前认为把表覆盖整个页面时表高就等于页面高度了!

//页面总高度double pageHeight = doc.getFirstSection().getPageSetup().getPageHeight();

文档里是有方法可以直接获取到页面高度的
想当然的后果就是所有数据都计算好了渲染时总是会多一行或者少一行!而且是找不到原因!
最后自己写方法计算了一页中表最大能多高,再配合计算就能分毫不差了。

还有就是inset函数是将新行插入到索引的上方!其实也好理解文档里两个方法可以在已有表中插入新行,分别为insert和add
其中insert是可以指定索引的,我一般喜欢用这个,他的意思就是把新行插入到这个索引位置,当然原本在这个位置的行就会往后排,这样想就理解了,当时是死记的:insert是插入到索引行上的一行。就导致遇到误差是否认你自己!很耽误时间!
add就好理解了 在别的最后加上新行 他不能指定索引。
最后效果如下:
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com