我们一般导出execl都具有固定的表格形式,但有一天客户对我说如果execl内容超一页后,每次打印的时候,只有第一页有表头,最后一页有表尾,给他们带来很大的麻烦,要求我给他们改一下。

查阅大量的资料结果没有给出具体的方法可以实现改需求,然后我想在导出execl之后对他添加一个固定的表头表尾,但是这个情况就会出现一个问题,需要知到表头表尾的大小和打印时每页的单元格数量,因为不确定单元格是否会出现自动换行,所以需要遍历循环当前所有的单元格,累加后判断是否超出一页。废话不多说,上代码。

//读取所有行
int totalRows = sheet.getPhysicalNumberOfRows();

读取的所有行包括设置格式后的数量,所以要保证导出的模板中没有任何格式,要不然会出现导出实际数量小于查询的数量。

也可以使用下面的方法,会过滤空白的单元行

    /*** @Author haojl* @Description 读取execl行数* @Date 2021/10/29 15:14* @Param [wb]* @return int**/public static int readExeclAllRows(Workbook wb){Sheet sheet = wb.getSheetAt(0);CellReference cellReference = new CellReference("A4");boolean flag = false;System.out.println("总行数:"+(sheet.getLastRowNum()+1));for (int i = cellReference.getRow(); i <= sheet.getLastRowNum();) {Row r = sheet.getRow(i);if(r == null){// 如果是空行(即没有任何数据、格式),直接把它以下的数据往上移动sheet.shiftRows(i+1, sheet.getLastRowNum(),-1);continue;}flag = false;for(Cell c:r){if(c.getCellType() != Cell.CELL_TYPE_BLANK){flag = true;break;}}if(flag){i++;continue;}else{ //如果是空白行(即可能没有数据,但是有一定格式)//如果到了最后一行,直接将那一行remove掉if(i == sheet.getLastRowNum()) {sheet.removeRow(r);} else {//如果还没到最后一行,则数据往上移一行sheet.shiftRows(i+1, sheet.getLastRowNum(),-1);}}}System.out.println("总行数:"+(sheet.getLastRowNum()+1));return sheet.getLastRowNum()+1;}

正常没有格式的单元格大小为13.5,每页打印的数量为50行,所以我需要去除要添加尾部的大小

    /*** @Author haojl* @Description 判断当前行是否超过一页* @Date 2021/10/29 10:15* @Param [rows, allRows, wb, sheet]* @return boolean**/public static int findLastRow(int rows,int allRows,Workbook wb,Sheet sheet){int lastRows = 0;//当前页行高double AllHeight = 0;//当前行行高double height;for(int i=rows;i<allRows;i++){height = sheet.getRow(i).getHeight() / 20;double nextHeight = AllHeight + height;if(AllHeight <= 500 && nextHeight >= 500){lastRows = i;break;}else if(i == allRows-1){lastRows = i;}AllHeight += height;}return lastRows;}

在插入表尾时需要添加空白行,这样不会使数据丢失

    /*** @Author haojl* @Description 插入空白行* @Date 2021/10/28 17:30* @Param [wb, sheet, starRow, rows]* @return void**/public static void insertRow(HSSFWorkbook wb, HSSFSheet sheet, int starRow,int rows) {sheet.shiftRows(starRow + 1, sheet.getLastRowNum(), rows,true,false);starRow = starRow - 1;for (int i = 0; i < rows; i++) {HSSFRow sourceRow = null;HSSFRow targetRow = null;HSSFCell sourceCell = null;HSSFCell targetCell = null;short m;starRow = starRow + 1;sourceRow = sheet.getRow(starRow);targetRow = sheet.createRow(starRow + 1);targetRow.setHeight(sourceRow.getHeight());for (m = sourceRow.getFirstCellNum(); m < sourceRow.getLastCellNum(); m++) {sourceCell = sourceRow.getCell(m);targetCell = targetRow.createCell(m);targetCell.setCellStyle(sourceCell.getCellStyle());targetCell.setCellType(sourceCell.getCellType());}}}

添加表尾的时候要留出下一页表头的行数,这样保证数据正确。我们一般设置模板的时候就会把表头预设,这样通过下面方法把表头信息复制到指定位置

    /*** @Author haojl* @Description 这个函数是复制行到制定行的,* 其中第一个参数startRow:为想要复制第一行的标示;* 第二个参数endRow为: 到此结束复制行的标示,* 第三个参数pPosition为:复制内容后要放到指定的位置的标示* @Date 2021/10/27 17:02* @Param [startRow, endRow, pPosition, sheet]* @return void**/public static void copyRows(int startRow, int endRow, int pPosition, HSSFSheet sheet) {int pStartRow = startRow - 1;int pEndRow = endRow - 1;int targetRowFrom;int targetRowTo;int columnCount;CellRangeAddress region = null;int i;int j;if (pStartRow == -1 || pEndRow == -1) {return;}// 拷贝合并的单元格for (i = 0; i < sheet.getNumMergedRegions(); i++) {region = sheet.getMergedRegion(i);if ((region.getFirstRow() >= pStartRow)&& (region.getLastRow() <= pEndRow)) {targetRowFrom = region.getFirstRow() - pStartRow + pPosition;targetRowTo = region.getLastRow() - pStartRow + pPosition;CellRangeAddress newRegion = region.copy();newRegion.setFirstRow(targetRowFrom);newRegion.setFirstColumn(region.getFirstColumn());newRegion.setLastRow(targetRowTo);newRegion.setLastColumn(region.getLastColumn());sheet.addMergedRegion(newRegion);}}// 设置列宽for (i = pStartRow; i <= pEndRow; i++) {HSSFRow sourceRow = sheet.getRow(i);columnCount = sourceRow.getLastCellNum();if (sourceRow != null) {HSSFRow newRow = sheet.createRow(pPosition - pStartRow + i);newRow.setHeight(sourceRow.getHeight());for (j = 0; j < columnCount; j++) {HSSFCell templateCell = sourceRow.getCell(j);if (templateCell != null) {HSSFCell newCell = newRow.createCell(j);copyCell(templateCell, newCell);}}}}}public static void copyCell(HSSFCell srcCell, HSSFCell distCell) {distCell.setCellStyle(srcCell.getCellStyle());if (srcCell.getCellComment() != null) {distCell.setCellComment(srcCell.getCellComment());}int srcCellType = srcCell.getCellType();distCell.setCellType(srcCellType);if (srcCellType == HSSFCell.CELL_TYPE_NUMERIC) {if (HSSFDateUtil.isCellDateFormatted(srcCell)) {distCell.setCellValue(srcCell.getDateCellValue());} else {distCell.setCellValue(srcCell.getNumericCellValue());}} else if (srcCellType == HSSFCell.CELL_TYPE_STRING) {distCell.setCellValue(srcCell.getRichStringCellValue());} else if (srcCellType == HSSFCell.CELL_TYPE_BLANK) {// nothing21} else if (srcCellType == HSSFCell.CELL_TYPE_BOOLEAN) {distCell.setCellValue(srcCell.getBooleanCellValue());} else if (srcCellType == HSSFCell.CELL_TYPE_ERROR) {distCell.setCellErrorValue(srcCell.getErrorCellValue());} else if (srcCellType == HSSFCell.CELL_TYPE_FORMULA) {distCell.setCellFormula(srcCell.getCellFormula());} else { // nothing29}}

最后一页的时候不要忘记把表尾加上。这样一个自带表头表尾的execl就完成了。

因为我们之前在计算表格行数的时候没有设置格式,这样打印的时候都是没有表格的,下面的方法是设置打印时具有表格的方法。

    /*** @Author haojl* @Description 设置execl打印时具有网格* @Date 2021/10/28 9:10* @Param [wb, sheet, filePath, sheetIndex, startColumn, endColumn, startRow, endRow]* @return void**/public static void printWG(HSSFWorkbook wb,HSSFSheet sheet,String filePath,int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) throws Exception {//set print area with indexeswb.setPrintArea(sheetIndex, startColumn, endColumn, startRow, endRow);//set paper sizesheet.getPrintSetup().setPaperSize(XSSFPrintSetup.A4_PAPERSIZE);//set display grid lines or notsheet.setDisplayGridlines(true);//set print grid lines or notsheet.setPrintGridlines(true);FileOutputStream out = new FileOutputStream(new File(filePath));wb.write(out);out.close();System.out.println("xlsx written successfully");}

我这个方法是在execl没有生成的时候添加的,所以各位看官按照各自的需求进行调整一下。

poi导出execl固定表头表尾相关推荐

  1. EXCEL上固定表头表尾

    目标:excel中固定表头(无论怎么拖动拉条,表头都是固定不动的,只有中间的数据动) 示例: 姓名 性别 年龄    李      男      28   王      男      27 刘     ...

  2. POI导出设置复杂表头

    POI导出设置复杂表头 先展示一下表头结构 工具类 /*** 生成表格(用于生成复杂表头)* * @param sheetName sheet名称* @param wb 表对象* @param cel ...

  3. POI导出Execl文件,使JAVA虚拟机OOM

    由于在项目中使用POI导出execl,导致JAVA虚拟机OOM,采用以下方式解决问题: 原先方式: g_wb = new XSSFWorkbook(sourceFile.getInputStream( ...

  4. 【Easyexcel】使用easyexcel导出带有固定表头的excel代码,并且有合并单元格操作

    以下是一个使用EasyExcel导出带有固定表头并且带有合并单元格的Excel代码示例: //创建excel对象 ExcelWriter writer = EasyExcel.write(" ...

  5. 广义表取表头表尾_数据结构广义表的递归算法

    Hello同学们,又到了美妙的星期三,很开心又和大家见面了.这次我们要来讲一讲关于广义表的那些事儿! 俗语说:"与其临渊羡鱼,不如退而结网." 希望通过今天的学习大家可以有所收获. ...

  6. excel 设置表头表尾

    Excel按钮调用宏 今天我们用动画的形式介绍在Excel中用按钮调用"宏"的方法和技巧. 如果宏对所有工作簿文档有效,建议大家在工具栏上添加一个命令按钮,用来调用宏. 操作方法如 ...

  7. iOS开发,tableView在Grouped样式下,表头表尾空白问题解决

    1.estimatedRowHeight.estimatedSectionHeaderHeight.estimatedSectionFooterHeight均设为0 2.表头高度sectionHead ...

  8. 使用 colgroup标签实现表头表尾固定,中间内容自适应

    话不多说,直接上代码: <table style="width: 99%;borderTop:1px solid #000;borderLeft:1px solid #000" ...

  9. POI导出支持合并表头及单元格锁定的Excel

    1.开发前提 目前项目上有这样的需求,支持Excel导出后再线下调至后导入,并且有关键字及其他部分字段不支持修改,所以需要写保护,按正常的理解来讲锁定特定的列即可,但是需求中需要在Excel中添加行数 ...

  10. JSP表格模板升级(4)-- 表头和表尾固定的表格模板

    上文<JSP表格模板升级(3)--可变列数的表格模板>已经完成了一个功能几近完善的表格模板,直接可以用于大部分二维表格的显示需求.本文中我们将改变表格底层的实现,将table标签替换为更加 ...

最新文章

  1. Scrapy_splash组件的使用
  2. pycharm的中自定义库和关键字_Python“库”在树莓派中的应用解析
  3. 用cocos2d-html5做的消除类游戏《英雄爱消除》(1)——系统主菜单
  4. (转)基于Metronic的Bootstrap开发框架经验总结(2)--列表分页处理和插件JSTree的使用...
  5. 7000字整理: 全网最详细Pandas合并数据集操作总结
  6. java hibernate回滚_Spring Hibernate 测试事务不能回滚
  7. 前端开源项目周报0214
  8. POJ NOI0105-36 计算多项式的值
  9. [转载] Python—urllib模块
  10. idata 单片机 新唐_半导体新唐单片机怎么样_新唐单片机是台湾的吗
  11. android自定义换行居中CenterTextView
  12. 20172324《程序设计与数据结构》第一周学习总结
  13. 深信服scsa知识点一
  14. Open Inventor与Coin3D开发环境配置/Vs2017+Qt+coin3D配置方法,实测可用
  15. Qt各版本官方下载地址
  16. 【STL容器讲解—栈队列】
  17. android 开发客户端开发,【Android应用】Android网站客户端的开发介绍(1)
  18. vue首次赋值不触发watch及watch和computed的区别
  19. 嵌入式AI开发:Maixduino目标识别分类
  20. 低风险整体式微服务演进第二部分

热门文章

  1. Round14—最小生成树
  2. 低频声音功率放大器电子设计报告
  3. 谷歌浏览器访问接口无返回
  4. 嵌入式c语言小学期实验报告,小学期单片机实验报告.doc
  5. java 分布式系统架构_什么是分布式系统!以及分布式系统架构的优缺点
  6. ds90ub934 i2c 配置_TI ds90ub954 芯片调试简单总结
  7. 使用imp导入工具导入dmp文件
  8. abaqus -复合材料
  9. 上海大华条码称代码_大华条码秤设置方法
  10. npm/cnpm install 报错 platform unsupported