1.导入excel:MultipartFile file 解析成指定对象list
2. 关于POI读取excel中数字,丢失精度,如:表格数值11.2 ,解析出来是11.19999999...
第一步:
//前端传递file....
MultipartFile file = new MultipartFile();
// 先验证数据在上传
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
//校验"文件不能为空"
}
if (!(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
//校验格式:"请选择xls文件上传"
}
//工具类对象传递 自定义的 dto 字段与excel对应
ExcelUtil accessReqExcelUtil = new ExcelUtil<>(ExcelDto.class);
List accessList = Lists.newArrayList();
try {
//调用方法返回list,也可以自定义方法名称,传参
accessList = accessReqExcelUtil.importExcel(file);
} catch (Exception e) {
e.printStackTrace();
}
//后续逻辑...
第二步、调用工具类:
/**
* Excel工具类
* */
public class ExcelUtil {
public Class clazz;
public ExcelUtil(Class clazz)
{
this.clazz = clazz;
}
/**
* 读取Excel内容转为List
*/
public List importExcel(MultipartFile file) throws Exception{
return importExcel(StringUtils.EMPTY, file);
}
/**
* 读取Excel内容转为List
*/
public List importExcel(String sheetName, MultipartFile file) throws Exception {
U.assertException(U.isBlank(file),"上传的文件为空");
//获取文件名
String fileName = file.getOriginalFilename();
U.assertException(!(fileName.endsWith(".xls") || fileName.endsWith(".xlsx")), "请选择Excel文件上传");
//
List list = new ArrayList<>();
Workbook workbook = WorkbookFactory.create(file.getInputStream());
Sheet sheet;
if (StringUtils.isNotEmpty(sheetName)){
// 如果指定sheet名,则取指定sheet中的内容.
sheet = workbook.getSheet(sheetName);
} else {
// 如果传入的sheet名不存在则默认指向第1个sheet.
sheet = workbook.getSheetAt(0);
}
if (sheet == null) throw new IOException("文件sheet不存在");
//获取数据
int rows = sheet.getLastRowNum();
if(rows==0) U.assertException("当前工作簿没数据");
//行号从0开始,所以需要+1
rows = rows+1;
// 默认序号
int serialNum = 0;
// 有数据时才处理 得到类的所有field.
Field[] allFields = clazz.getDeclaredFields();
//用于校验是否存在某些字段
Map fieldNameMap = new HashMap<>();
// 定义一个map用于存放列的序号和field.
Map fieldsMap = new HashMap<>();
for (Field field : allFields) {
// 设置类的私有字段属性可访问.
field.setAccessible(true);
fieldsMap.put(++serialNum, field);
fieldNameMap.put(field.getName(),field);
}
//
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DateFormatType.YYYY_MM_DD_HH_MM_SS.getValue());
DateTimeFormatter df = DateTimeFormatter.ofPattern(DateFormatType.YYYY_MM_DD.getValue());
SimpleDateFormat sdf = new SimpleDateFormat(DateFormatType.YYYY_MM_DD_HH_MM_SS.getValue());
//
Row row = null;
Cell cell = null;
try{
// 从第2行开始取数据,默认第一行是表头.
for (int i = 1; i < rows; i++) {
row = sheet.getRow(i);
if (row==null) continue;
T entity = clazz.newInstance();
for (int j = 0; j < serialNum; j++) {
cell = row.getCell(j);
if (cell == null) continue;
// 从map中得到对应列的field.
Field field = fieldsMap.get(j + 1);
// 取得类型,并根据对象类型设置值.
Class> fieldType = field.getType();
String c;
//excel数字精度问题:如果是数字类型,转化
if (cell.getCellTypeEnum().equals(CellType.NUMERIC) && fieldType != Date.class) {
NumberFormat numberFormat = NumberFormat.getNumberInstance();
double d = cell.getNumericCellValue();
// 关键在这里!
c = numberFormat.format(d);
} else {
// 先设置Cell的类型,然后就可以把纯数字作为String类型读进来了(这里数字类型 c可能存在精度问题)
cell.setCellType(CellType.STRING);
c = cell.getStringCellValue();
}
if (StringUtils.isEmpty(c)) continue;
if (String.class == fieldType) {
field.set(entity, c);
} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
field.set(entity, Integer.parseInt(c));
} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
field.set(entity, Long.valueOf(c));
} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
field.set(entity, Float.valueOf(c));
}else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
field.set(entity, Short.valueOf(c));
} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
field.set(entity, Double.valueOf(c));
} else if (Character.TYPE == fieldType) {
if (c.length() > 0) {
field.set(entity, c.charAt(0));
}
} else if (Date.class == fieldType) {
if (cell.getCellTypeEnum() == CellType.NUMERIC) {
cell.setCellValue(sdf.format(cell.getNumericCellValue()));
c = sdf.format(cell.getNumericCellValue());
} else {
c = cell.getStringCellValue();
}
} else if (java.math.BigDecimal.class == fieldType) {
try{
field.set(entity, NumberUtil.toBigDecimal(c));
}catch (Exception ex){
U.assertException("数值类型转换失败,请检查单元格值是否符合规范");
}
} else if (LocalDateTime.class == fieldType) {
field.set(entity, LocalDateTime.parse(excelDoubleToDate(c, DateFormatType.YYYY_MM_DD_HH_MM_SS),dtf));
}else if (LocalDate.class == fieldType) {
field.set(entity, LocalDate.parse(excelDoubleToDate(c,DateFormatType.YYYY_MM_DD),df));
}
}
if (BeanUtil.isNotEmpty(entity)) {
//判断是否有行号字段,有的话赋值
if (fieldNameMap.containsKey("rowNum")){
//记录一下行数
fieldNameMap.get("rowNum").set(entity,row.getRowNum()+1);
}
list.add(entity);
}
}
}catch (Exception ex){
ex.printStackTrace();
U.assertException(StrUtil.format("解析第{}行,第{}列时出错,错误原因:{}",
row==null?"null":row.getRowNum()+1,
cell==null?"null":cell.getColumnIndex()+1,
ex.getMessage()));
}
return list;
}
//解析Excel日期格式
public static String excelDoubleToDate(String strDate,DateFormatType dateFormatType) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormatType.getValue());
Date tDate = doubleToDate(Double.parseDouble(strDate));
return sdf.format(tDate);
}catch (Exception e){
//e.printStackTrace();
return strDate;
}
}
}