项目场景:
在项目开发中,经常会遇到导出数据到excel表和利用excel表批量导入数据的需求,最常用的是利用POI进行导出导入操作;
问题描述:
导入一个有数据的excel文件, 导入成功后,再导出,对导出的excel文件不做任何处理再进行导入操作,java poi 解析不到数据; 如果将导出的excel文件打开随便点一下,保存再导入,此时可以解析到数据,之前取单元格值代码如下:
XSSFCell cell = row.getCell(j);
if (null == cell) {
continue;
}
// 获取当前行当前列的值并进行保存s
// 要对列进行类型的转化
if (22 == cell.getCellStyle().getDataFormat()) {
Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
String dateStr = sdf.format(date);
ss[j] = dateStr;
} else {
cell.setCellType(CellType.STRING);
ss[j] = cell.getStringCellValue();
}
原因分析:
有文章说是导入、导出时都要设置CellType,查看代码发现导入的时候设置了cell.setCellType(CellType.STRING),导出没写,后来在导出的时候也进行设置newCell.setCellType(CellType.STRING),但是没效果,后经调试,发现cell值取值能取到,但是进行设置cellType后再去取值,取不到值,猜测是不是因为poi中cell.setCellType(CellType.STRING)过期问题导致的,于是替换采用DataFormatter进行格式化,去取单元格中的值。
解决方案:
对单元格的值使用DataFormatter对象格式化,直接获取,修改后代码如下:
XSSFCell cell = row.getCell(j);
if (null == cell) {
continue;
}
// 获取当前行当前列的值并进行保存s
// 要对列进行类型的转化
if (22 == cell.getCellStyle().getDataFormat()) {
Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
String dateStr = sdf.format(date);
ss[j] = dateStr;
} else {
//直接获取到单元格的值
DataFormatter formatter = new DataFormatter();
ss[j] = formatter.formatCellValue(cell);
}
此时单元格中的值能正常解析到。
查看DataFormatter对象formatCellValue()方法源码,发现方法中对单元格中的值都做了类型转换处理:
public String formatCellValue(Cell cell, FormulaEvaluator evaluator, ConditionalFormattingEvaluator cfEvaluator) {
this.localeChangedObservable.checkForLocaleChange();
if (cell == null) {
return "";
} else {
CellType cellType = cell.getCellType();
if (cellType == CellType.FORMULA) {
if (evaluator == null) {
return cell.getCellFormula();
}
cellType = evaluator.evaluateFormulaCell(cell);
}
switch(cellType) {
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell, cfEvaluator)) {
return this.getFormattedDateString(cell, cfEvaluator);
}
return this.getFormattedNumberString(cell, cfEvaluator);
case STRING:
return cell.getRichStringCellValue().getString();
case BOOLEAN:
return cell.getBooleanCellValue() ? "TRUE" : "FALSE";
case BLANK:
return "";
case ERROR:
return FormulaError.forInt(cell.getErrorCellValue()).getString();
default:
throw new RuntimeException("Unexpected celltype (" + cellType + ")");
}
}
}
完美解决导出excel表,不做任何操作直接导入,读取数据失效的问题~~~!!!