poi版本:org.apache.poi_3.7.0.jar
我使用poi的时候不多所以不太熟练
今天使用poi读取含有公式列的xls导致报错,研究poi的api后使用以下代码解决公式类型读取失败错误
特此记录
重要的方法是读取单个单元格数据的方法,所有需适配的单元格数据类型都要在这个方法处理,已处理的数据类型有公式,日期,数字等…如需其他数据类型读取,修改方法即可
/**
* 读取excel 第1张sheet (xls和xlsx)
*
* @param filePath excel路径
* @param headerRow 标题所在的行序号(第几行)
* @return
*/
public List<Map<String, String>> readExcelTest(String filePath,int headerRow) {
Sheet sheet = null;
Row row = null;
Row rowHeader = null;
List<Map<String, String>> list = null;
String cellData = null;
Workbook wb = null;
if (filePath == null) {
return null;
}
String extString = filePath.substring(filePath.lastIndexOf("."));
InputStream is = null;
try {
is = new FileInputStream(filePath);
if (".xls".equals(extString)) {
wb = new HSSFWorkbook(is);
} else if (".xlsx".equals(extString)) {
wb = new XSSFWorkbook(is);
} else {
wb = null;
}
if (wb == null) {
throw new RuntimeException("xls为空!");
}
// 用来存放表中数据
list = new ArrayList<Map<String, String>>();
// 获取第一个sheet
sheet = wb.getSheetAt(0);
// 获取最大行数
int rownum = sheet.getPhysicalNumberOfRows();
// 获取标题行
rowHeader = sheet.getRow(headerRow-1);
// 获取最大列数
int colnum = rowHeader.getPhysicalNumberOfCells();
//获取标题行所有列名
List<String> headerList = new ArrayList<String>();
for(int i = 0; i < colnum; i++) {
cellData = (String) getCellFormatValue(rowHeader.getCell(i));
headerList.add(cellData);
}
//获取每一行对应的列值
for (int i = headerRow; i < rownum; i++) {
Map<String, String> map = new HashMap<String, String>();
row = sheet.getRow(i);
if (row != null) {
for(int j = 0;j<headerList.size();j++) {
cellData = (String) getCellFormatValue(row.getCell(j));
if(StringUtils.isNotBlank(cellData)) {
map.put(headerList.get(j), cellData.trim());
}
}
} else {
continue;
}
if(!map.isEmpty()) {
list.add(map);
}
}
for(int k = 0;k<list.size();k++) {
for(int n = 0;n<headerList.size();n++) {
System.out.print(list.get(k).get(headerList.get(n)));
System.out.print("\t");
}
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 获取单个单元格数据(所有需要适配的单元格类型都要在这个方法处理)
*
* @param cell 单元格
* @return Object 单元格数据
*/
public Object getCellFormatValue(Cell cell) {
Object cellValue = null;
if (cell == null) {
return "";
}
//cell 类型
int cellType = cell.getCellType();
//公式类型处理
if(cellType==Cell.CELL_TYPE_FORMULA) {
//获取公式结果的cell类型
cellType=cell.getCachedFormulaResultType();
}
// 判断cell类型
switch (cellType) {
//数字类型
case Cell.CELL_TYPE_NUMERIC: {
//如果为日期类型
if (DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
//日期格式format
cellValue = new SimpleDateFormat("yyyyMMdd").format(date);
return cellValue;
}
//保留小数位format
cellValue = new DecimalFormat("#").format(cell.getNumericCellValue());
break;
}
//字符串类型
case Cell.CELL_TYPE_STRING: {
cellValue = cell.getRichStringCellValue().getString();
break;
}
default:
cellValue = "";
}
return cellValue;
}