POI excel导入解析成list;(解决数字精度问题)

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;
        }
    }
}

你可能感兴趣的:(java,maven,spring)