poi解析excel出现格式不正确

最近有客户用最新的excel格式,即后缀为xlsx的excel做系统导入时出现bug,原来系统用来解析excel的的技术是jxl。jxl已经老早就不更新了不再支持excel后续版本的读写,没办法,只能用Apache的poi来实现。简单的使用百度一大堆,不需要我多写了,在开发的过程中遇到了些问题,就把解决方法记录下来方便日后查看。为了同时兼容03、07及更高版本的excel。(恶心的是后缀是xlsx还会分两个格式ole2和ooxml),在创建工作簿的时候做了判断,当然这是百度过后的解决方案。。。

public static Workbook create(InputStream in) throws IOException,InvalidFormatException {
	    if (!in.markSupported()) { //hasPOIFSHeader和hasOOXMLHeader的要求,inputStream must support mark and reset, or be a PushbackInputStream
	        in = new PushbackInputStream(in, 8);
	    }
	    if (POIFSFileSystem.hasPOIFSHeader(in)) { //后缀是xlsx但是是ole2格式的或更低版本
	        return new HSSFWorkbook(in);
	    }
	    if (POIXMLDocument.hasOOXMLHeader(in)) { //后缀是xlsx但是是OOXML格式的或更高版本
	        return new XSSFWorkbook(OPCPackage.open(in));
	    }
	    throw new IllegalArgumentException("你的excel版本目前poi解析不了");
	}

获取sheet,因为不确定生成哪种类的工作薄,所以这个用接口而不用实现类

Sheet sheet = this.workbook.getSheetAt(0);

接下来是获取列数和行数

行数用sheet.getLastRowNum();获取最后一行的num,就是实际的行数,

列数的话 Row row = sheet.getRow(1);  row.getPhysicalNumberOfCells();

但这两个方法都是只对于说表格做得很标准来说的方法,万一这个表有一些误操作导致的多一行或者多一列,好像api里面也没有那种说可以忽视空行或空列的方法,我想应该如果要做应该是自己在代码中另外写吧。

到获取单元格

Cell  cell = sheet.getRow(i).getCell(j);

i和j分别代表行和列,很好理解第几行第几列就能获取到单元格了,jxl里面则可以直接有个getcell(i,j)传两个参数直接获取。

但是他们之间还有不一样的地方就是,excel表格往往在做的时候会出现空单元格,jxl能直接认出来这是一个emptycell,但是poi则会给我们直接抛出了空指针异常,鉴于这种情况,我的做法是遇到就把那个cell初始化成一个单元格类型为空白的单元格,毕竟空指针异常很让人讨厌。。。一报异常程序就中断了。

cell = sheet.getRow(i).createCell(j);
cell.setCellType(Cell.CELL_TYPE_BLANK);

对日期格式的判断,poi不像jxl有date类型,poi单元格格式只有这几种

static int CELL_TYPE_BLANK
          Blank Cell type (3)
static int CELL_TYPE_BOOLEAN
          Boolean Cell type (4)
static int CELL_TYPE_ERROR
          Error Cell type (5)
static int CELL_TYPE_FORMULA
          Formula Cell type (2)
static int CELL_TYPE_NUMERIC
          Numeric Cell type (0)
static int CELL_TYPE_STRING
          String Cell type (1)
在poi日期被当做是数值类型,因此我们可以这么做

if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
//还需要判断是否是日期格式
if (HSSFDateUtil.isCellDateFormatted(cell)){
//该干嘛干嘛....
}
}
有时候excel表格里面有手机号。设置了单元格格式为文本没问题,但是如过没设,手机11位数,读取出来会用科学计数法的,所以应该做个format,避免科学计数法

DecimalFormat df = new DecimalFormat("0"); //可避免科学计数法
strTmp = df.format(cell.getNumericCellValue());
暂时遇到就那么多问题以及他们的解决方案,如果有更好的还希望评论让我看到,学习学习。



你可能感兴趣的:(Java)