写在前面
最近做了一个解析excel,将数据转为sql文件的小工具,本文分享在使用POI工具类解析excel过程中所踩过的坑。
主要使用的jar包
poi-3.11
log4j-1.2.17
遇到的问题及解决方案
1.遇到sheet表单中有空行时
当使用sheet.getLastRowNum()或sheet.getPhysicalNumberOfRows()来获取当前表格的行数时,若表格中(首行到最后有数据的一行)存在空行,会跳过空行不计数。差别:当使用getLastRowNum()之后遇到空行,通过sheet.getRow(rowindex)将获取不到该行之后的数据,而getPhysicalNumberOfRows()可以。
因为无格式空行不计数,通过循环以getPhysicalNumberOfRows()取得的值遍历sheet时,通过cell.getCellType方法会报错(cell无格式,row.getCell(i)的返回值为null),因此,想要去cell的值需要先判断cell是否为空以及cell的样式:
if(null==cell||cell.getCellType()==XSSFCell.CELL_TYPE_BLANK) {
//TODO...
}
如果对获取的cell的值的类型不做要求,可以在获取cell的value之前将cell的type统一设置为String(表格中大部分格式不是固定的一种,转为字符串类型方便处理数据)
cell.setCellType(XSSFCell.CELL_TYPE_STRING);
String s = cell.getStringCellValue();
2.Cell中的数据是使用函数计算出来的值
转为String便会直接将表达式输出,而不是计算出来的结果。
解决方案:
在转为String类型之前对cell是否为FORMULA类型进行判断,若是,先将值计算出来再转。
XSSFFormulaEvaluator e = new XSSFFormulaEvaluator(workbook);//放在循环体之外
if (cell.getCellType() == XSSFCell.CELL_TYPE_FORMULA) {
cell = e.evaluateInCell(cell);
}
3.遇到cell为空且在row末尾时
当cell为空且处于一行的末尾时(相对于表头),遍历row的前提是确定row的cell数量,row的getLastCellNum()方法与getPhysicalNumberOfCells()方法与前文的sheet获取row数量的两种方法类似,如果仅仅是为了获取数据而言,无伤大雅;但是大多数情况解析excel获取数据的目的是对数据进行进一步的处理,这样就会造成一个严重的结果——每一行的列数不一致导致取得字符串的数目不一致(即使最后一行没有值,也需要用””替代,但因为循环的次数达不到而无法处理)。
解决方案:
规定要读取的每一行的列数。
表格中的数据与表头相关,若没有表头,这一列的数据便没有意义,因此可以通过获取第一行的列数来作为整个表格每行需要读取的列数。
static int cellNum;//类的静态变量
protected String getSheetHeader(XSSFSheet sheet) {
XSSFRow row = sheet.getRow(0);
//为静态变量赋值,仅在表头赋值一次
cellNum = row.getLastCel