随手记
功能需求:
传入一个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,但是实际却不是,看到调试结果也是一脸懵逼,不知道为什么,知道的小伙伴可以解释下。