最近有客户用最新的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) |
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
//还需要判断是否是日期格式
if (HSSFDateUtil.isCellDateFormatted(cell)){
//该干嘛干嘛....
}
}
有时候excel表格里面有手机号。设置了单元格格式为文本没问题,但是如过没设,手机11位数,读取出来会用科学计数法的,所以应该做个format,避免科学计数法
DecimalFormat df = new DecimalFormat("0"); //可避免科学计数法
strTmp = df.format(cell.getNumericCellValue());
暂时遇到就那么多问题以及他们的解决方案,如果有更好的还希望评论让我看到,学习学习。