poi导出execl固定表头表尾

本文介绍如何在导出Excel时,为内容超过一页的情况添加固定表头和表尾,以确保打印时始终包含表头,同时处理单元格自动换行及页面布局。通过编程实现行数计算、格式调整和打印设置,创建自定义的带表头表尾的Excel模板。
摘要由CSDN通过智能技术生成

我们一般导出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 indexes
        wb.setPrintArea(sheetIndex, startColumn, endColumn, startRow, endRow);
        //set paper size
        sheet.getPrintSetup().setPaperSize(XSSFPrintSetup.A4_PAPERSIZE);
        //set display grid lines or not
        sheet.setDisplayGridlines(true);
        //set print grid lines or not
        sheet.setPrintGridlines(true);
        FileOutputStream out = new FileOutputStream(new File(filePath));
        wb.write(out);
        out.close();
        System.out.println("xlsx written successfully");
    }

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值