基于POI对Excel生成解析做的简单封装
原因:
最近开始的新工作涉及到excel的导入导出,而且发现其他几个小伙伴的任务都有涉及到。感觉大家都在做重复工作。难道每一种模板的excel都要复制代码,然后改一改。所以想着封装一个工具类,提供给大家使用。
目录解释

效果
上传
使用postman模拟文件上传,具体数据如下:

上传文件后将数据解析放在集合中。

重写SaveDataInterface接口后实现数据保存功能。

下载
请求:localhost:8080/downLoadExcel

内容如下:

部分代码
部分代码
- 上传下载入口
@Controller
public class PoiExcelController {@AutowiredPoiExcelService poiExcelService;@ResponseBody@RequestMapping(value = "/fileUpload",method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)public List 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 saveDataInterface = new SaveDataInterface(){@Overridepublic int save(T t) {if(t instanceof Teacher){Teacher teacher = (Teacher) t;return poiExcelService.saveUserInfo(teacher);}return 0;}};//具体解析excel方法List 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 list = poiExcelService.getUserInfo();//下载excel第一行各列名称及对应实体属性字段Map title = new HashMap();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);}
}
- 上传解析
/*** 将上传的文件解析成集合对象* 该方法只支持简单数据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 实体类的类型* @return* @throws Exception*/public static List parseExcelToList(MultipartFile file, Map map, DateFormat dateFormat, boolean flag, SaveDataInterface saveDataInterface, Class clazz) throws Exception {//文件扩展名校验及是否是office文件校验checkExtensionAndType(file);List list = new ArrayList();try {//正确的文件类型 自动判断2003或者2007Workbook workbook = PoiUtils.getWorkbookAuto(file);//默认只有一个sheetSheet sheet = workbook.getSheetAt(0);//获得sheet有多少行int rows = sheet.getPhysicalNumberOfRows();//读第一个sheetfor (int i = 0; i < rows; i++){//flag为ture标识第一行需要解析,false为不需要解析if(!flag && i == 0){continue;}Row row = sheet.getRow(i);//通过反射获取无产构造器Constructor 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;}
- 下载解析
private static void parseExcelCell(Map map, DateFormat dateFormat, Class 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
代码基本实现了功能,不过感觉封装的不太好(比如异常还没处理,日志也没有规范的打印,后期会修正)。如果有更好的封装和想法,也可以留言分享给我,谢谢!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
