首页 > 技术文章 > java去掉excel空行报错

caihonghai 2021-01-25 19:52 原文

随手记

 

功能需求:

传入一个excel,删除其中所有空行,返回新的excel

 

出现问题:

删除空行后的文件,可以正常打开,但是接下的代码处理会报错:

Invalid column index (-1). Allowable column range for BIFF8 is (0..255) or (‘A‘..‘IV‘) xxxxxx 异常

 

调试报错代码,发现代码处理excel时,sheet的row数目与实际的数量不一致。

原本excel数据:

去掉空行后的excel:

但是处理后的excel,sheet页对象的row数据还有4行,并不是看到的2行。

初步判断还有两个空行没过滤掉

 

解决代码

   /**
     * @param firstRow       从第几行开始检测空行
     * @param inPutFilePath  文件路径
     * @param outPutFilePath 文件写出路径
     * @return void
     * @throws
     * @Author hxh
     * @Date 2021-01-25 16:32:16
     * @Desc: 去除excel里的空行
     */
    public static void trimExcel(int firstRow, String inPutFilePath, String outPutFilePath) {
        Workbook wb = null;
        if (inPutFilePath == null) {
            return;
        }
        String extString = inPutFilePath.substring(inPutFilePath.lastIndexOf("."));
        InputStream is = null;
        try {
            is = new FileInputStream(inPutFilePath);
            if (extString.equals(".xls")) {
                wb = new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                wb = new XSSFWorkbook(is);
            } else {
                wb = null;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        Sheet sheet = null;
        Row row = null;
        String cellData = null;
        boolean empty = true;
        int useRows = firstRow;
        if (wb != null) {
            //获取第一个sheet
            sheet = wb.getSheetAt(0);
            //获取最大行数 从0开始算
            int rownum = Math.max(sheet.getLastRowNum(),sheet.getPhysicalNumberOfRows())+1;
            //获取最大列数
            int colnum = 0;
            for (int i = firstRow; i < rownum; i++) {
                row = sheet.getRow(i);
                if (row != null) {
                    colnum = Math.max( row.getLastCellNum(),row.getPhysicalNumberOfCells());
                    empty = true;
                    for (int j = 0; j < colnum; j++) {
                        cellData = (String) getCellFormatValue(row.getCell(j));
                        if (StringUtils.isNotBlank(cellData)) {
                            empty = false;
                            useRows++;
                            break;
                        }
                    }
                    if (empty) {
                        sheet.removeRow(row);
                        sheet.shiftRows(i + 1, rownum, -1);
                        i--;
                        rownum--;
                    }

                } else {
                    sheet.shiftRows(i + 1, rownum, -1);
                    i--;
                    rownum--;
                }
            }

//          rownum = sheet.getPhysicalNumberOfRows(); 
//      begin      这是个大坑!!!代码后来才加上去的
            rownum = Math.max(sheet.getLastRowNum(),sheet.getPhysicalNumberOfRows());
            for (int i=useRows;i<rownum;i++){
                row = sheet.getRow(i);
                sheet.removeRow(row);
            }
//      end      这是个大坑!!!代码后来才加上去的

            FileOutputStream out = null;
            try {
                out = new FileOutputStream(outPutFilePath);
                wb.write(out);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null)
                        out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

注意:

去掉空行后,调试发现

sheet.getPhysicalNumberOfRows();结果是4
sheet.getLastRowNum(); 结果是2

大坑,按照解释:

getPhysicalNumberOfRows()获取的是物理行数,也就是不包括那些空行(隔行)的情况。

getLastRowNum()获取的是最后一行的编号(编号从0开始)。

原以为getLastRowNum 一定会大于getPhysicalNumberOfRows,但是实际却不是,看到调试结果也是一脸懵逼,不知道为什么,知道的小伙伴可以解释下。

 

 

 

 

 

推荐阅读