基于POI对Excel生成解析做的简单封装

本文介绍了一种基于Apache POI库对Excel进行导入导出的简单封装,旨在避免重复工作。提供了上传和下载的示例,包括接口实现及部分关键代码,以帮助开发者快速集成到自己的项目中。作者还分享了GitHub仓库链接,欢迎反馈优化建议。
摘要由CSDN通过智能技术生成

原因:

        最近开始的新工作涉及到excel的导入导出,而且发现其他几个小伙伴的任务都有涉及到。感觉大家都在做重复工作。难道每一种模板的excel都要复制代码,然后改一改。所以想着封装一个工具类,提供给大家使用。

目录解释

在这里插入图片描述

效果

上传

        使用postman模拟文件上传,具体数据如下:
在这里插入图片描述
上传文件后将数据解析放在集合中。
在这里插入图片描述
        重写SaveDataInterface接口后实现数据保存功能。
在这里插入图片描述

下载

        请求:localhost:8080/downLoadExcel
在这里插入图片描述
内容如下:
在这里插入图片描述

部分代码

部分代码

  1. 上传下载入口
@Controller
public class PoiExcelController {

    @Autowired
    PoiExcelService poiExcelService;

    @ResponseBody
    @RequestMapping(value = "/fileUpload",method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public List<Teacher> fileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
       //excel列和即将封装到的实体中属性对应关系
        Map map = new HashMap();
        map.put("0", "id");
        map.put("1", "age");
        map.put("2", "flag");
        map.put("3", "name");
        map.put("4", "birthday");
        map.put("5", "money");
        //重写保存方法,用于存储数据
        SaveDataInterface<Teacher> saveDataInterface = new SaveDataInterface<Teacher>(){
            @Override
            public <T> int save(T t) {
                if(t instanceof Teacher){
                    Teacher teacher = (Teacher) t;
                    return poiExcelService.saveUserInfo(teacher);
                }
                return 0;
            }
        };
        //具体解析excel方法
        List<Teacher> list = ExcelParseUtils.parseExcelToList(file, map, false,saveDataInterface, Teacher.class);
        return list;
    }

    @RequestMapping(value = "downLoadExcel", method = RequestMethod.GET)
    public void downLoadExcel(HttpServletResponse response) throws Exception {
        List<Teacher> list = poiExcelService.getUserInfo();
        //下载excel第一行各列名称及对应实体属性字段
        Map<String, HeaderConfig> title = new HashMap<String, HeaderConfig>();
        title.put("0", new HeaderConfig("编号", "id"));
        title.put("1", new HeaderConfig("年龄", "age"));
        title.put("2", new HeaderConfig("标识", "flag"));
        title.put("3", new HeaderConfig("姓名", "name"));
        title.put("4", new HeaderConfig("生日", "birthday"));
        title.put("5", new HeaderConfig("余额", "money"));
        //下载后文件名
        String fileName = "teacher.xlsx";
        //将实体转成excel并输出给前端
        ExcelParseUtils.parseListToExcel(list, title, fileName, response);

    }
}
  1. 上传解析
/**
     * 将上传的文件解析成集合对象
     * 该方法只支持简单数据boolean, String, int, double,long,java.util.Date
     * 如果excel获取的类型和对象不一致,则认为对象中类型为字符串,将获取的值全部转换成String类型进行赋值。
     *
     * @param file 传文件流
     * @param map excel中列对应实体类中的属性,以0开头
     * @param dateFormat 如果有时间类型,时间类型格式化成什么样的字符串
     * @param flag 标识excle表格第一行是否需要解析成对象。默认不需要
     * @param saveDataInterface 钩子对象,如果需要保存数据,请实现接口,并重写方法(主要避免返回的list重新遍历存值)
     * @param clazz 将数据封装的目标对象类型
     * @param <T> 实体类的类型
     * @return
     * @throws Exception
     */
    public static <T> List<T> parseExcelToList(MultipartFile file, Map<String, String> map, DateFormat dateFormat, boolean flag, SaveDataInterface saveDataInterface, Class<T> clazz) throws Exception {
        //文件扩展名校验及是否是office文件校验
        checkExtensionAndType(file);

        List<T> list = new ArrayList<T>();
        try {
            //正确的文件类型 自动判断2003或者2007
            Workbook workbook = PoiUtils.getWorkbookAuto(file);

            //默认只有一个sheet
            Sheet sheet = workbook.getSheetAt(0);

            //获得sheet有多少行
            int rows = sheet.getPhysicalNumberOfRows();
            //读第一个sheet
            for (int i = 0; i < rows; i++){
                //flag为ture标识第一行需要解析,false为不需要解析
                if(!flag && i == 0){
                    continue;
                }
                Row row = sheet.getRow(i);
                //通过反射获取无产构造器
                Constructor<T> constructor = clazz.getConstructor();
                //创建对应的对象
                T t = constructor.newInstance();
                //遍历每行中的单元
                for (int j = 0; j < row.getLastCellNum(); j++){
                    // 列,每一列在map中对应着一个对象的属性
                    Cell cell = row.getCell(j);
                    if (cell != null){
                        //处理单元格数据
                        parseExcelCell(map, dateFormat, clazz, t, j, cell);
                    }
                }
                // 是不是可以放一个钩子,直接让别人创建接口子类,然后调用保存方法。建议不做处理,返回list后使用批量插入,避免重复建立数据库链接
                saveDataInterface.save(t);
                list.add(t);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
  1. 下载解析
 private static <T> void parseExcelCell(Map<String, String> map, DateFormat dateFormat, Class<T> clazz, T t, int j, Cell cell) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, ParseException {
        // 获取属性名称
        String fieldName = map.get(j + "");
        // 根据属性名获取属性对象
        Field field = clazz.getDeclaredField(fieldName);
        // 获取属性类型
        Class<?> fieldType = field.getType();

        // 获取属性对应的set方法名称
        String methodName = getFieldSetOrGetMethod(fieldName, "set");

        // 获取set方法对象
        Method method = clazz.getMethod(methodName, fieldType);
        logger.info("获取方法名:" + method.getName());
        // 默认时间格式化类型
        if(dateFormat == null){
            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        }
        // 获取单元格属性
        CellType cellTypeEnum = cell.getCellTypeEnum();
        // 布尔类型
        if(CellType.BOOLEAN.toString().equals(cellTypeEnum.toString())){
            handleBoolean(t, cell, fieldType, method);
            // 数值类型
        }else if(CellType.NUMERIC.toString().equals(cellTypeEnum.toString())){
            // 时间类型处理
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                handleDataNumeric(dateFormat, t, cell, fieldType, method);
            // 其他数值类型
            }else {
                handleOutherNumeric(t, cell, fieldType, method);
            }
        // 字符串
        }else if(CellType.STRING.toString().equals(cellTypeEnum.toString())){
            //上传日期是字符串,但是属性是时间类型
            if(fieldType == Date.class){
                handelDateStr(dateFormat, t, cell, method);
            }else {
                handleString(t, cell, method);
            }
        }
    }

最后

        只是简单封装,定制化的大家需要自己修改。感兴趣的小伙伴可以下载看看
        github地址:https://github.com/jiaxuch/poi-excel.git
        代码基本实现了功能,不过感觉封装的不太好(比如异常还没处理,日志也没有规范的打印,后期会修正)。如果有更好的封装和想法,也可以留言分享给我,谢谢!

Excel POI读取封装(文件+示范代码) package org.excel.service; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import javax.jws.WebService; import org.apache.poi.hssf.usermodel.*; import org.excel.data.DataType; import org.excel.data.DealForeign; import org.excel.data.ExcelImport; import org.excel.data.impl.StInStatusImpl; import org.excel.data.impl.StuClassImportImpl; import org.excel.data.impl.StuEducationImpl; import org.excel.data.impl.StuImprotDataImpl; import org.excel.data.impl.StuInClassImportImpl; import org.excel.data.impl.StuWorkStatusImpl; import org.excel.manager.Util; import org.excel.model.ExcelMap; import org.excel.xml.ExcelXmlParse; import net.sourceforge.jtds.jdbcx.JtdsDataSource; @WebService public class ExcelServiceImpl implements IExcelService { String tableName = ""; public static Integer suc = 0; public static Integer fail = 0; StringBuilder insert = new StringBuilder( " insert into {tableName} {column} values {values}"); /** 读取Excel表格数据 */ public List<HashMap> readExcel(String excelName, Integer sheetIndex, String startPoint, String endPoint) throws Exception { FileInputStream inputStream = null; inputStream = new FileInputStream(excelName); HSSFWorkbook workbook = new HSSFWorkbook(inputStream); HSSFSheet sheet = workbook.getSheetAt(sheetIndex); String[] sc = null;// 开始坐标 String[] ec = null;// 结束坐标 int startRow = 0;// 默认开始行数 int endRoe = sheet.getPhysicalNumberOfRows();// 默认结束行 int startLine = 0;// 默认开始列 int endLine = 0;// 结束列 if (startPoint != null && endPoint != null) { sc = startPoint.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值