前言
- 本次提供Excel工具类导入和导出的功能,是本人在借鉴网上的部分代码的基础上搭出一个公用化的工具。如有不妥之处,麻烦指明,本人不胜感激。
Excel导出
实现思路
- 通过Apache提供POI包读取Excel信息,首先读取指定字段名表头,其次从指定行数开始读取数据,然和对应的字段名映射到Map,最后返回一个List<Map>。在获取读取结果后通过调用Map映射到实体类工具,将Map中对应的值映射到实体中。这样子,只要规定好Excel模板和指定好表头读取行数和数据读取开始索引,就可以达到一个公用化的目的了。
实现步骤
- 导入Maven依赖
org.apache.poi poi 3.17 org.apache.poi poi-ooxml 3.17 org.apache.poi poi-ooxml-schemas 3.17 org.apache.poi poi-excelant 3.17 org.apache.poi poi-examples 3.17
- 定义上传Excel格式
- 接收MultiPartFile类型的数据
- 调用ExcelUtil 工具
ExcelUtils utils = new ExcelUtils();//字段名读取开始索引utils.setFieldReadIndex(4);//数据读取开始索引utils.setDataReadIndex(6);List
- 接收到List<Map>结果在MapToBeanUtils中映射。
for(Map map :maps){ //这里Bean是要用来接收的自定义实体类 Bean obj = MapToBeanUtils.getModel(map,Bean.class); //处理相关业务逻辑 }
Excel导出
实现思路
- 借助自定义注解在导出实体类的字段标注该字段对应的表头名称,再通过ExcelUtils工具解析实体类数据和其字段注解来生成Excel。
实现步骤
- 导入Maven依赖
org.apache.poi poi 3.17 org.apache.poi poi-ooxml 3.17 org.apache.poi poi-ooxml-schemas 3.17 org.apache.poi poi-excelant 3.17 org.apache.poi poi-examples 3.17
- 自定义注解
@Target(ElementType.FIELD)@Documented@Retention(RetentionPolicy.RUNTIME)public @interface ExcelColumn { String title();}
- 导出实体类引用注解形式
@ExcelColumn(title="uuid") private String uuid;
- 引用工具类
//这里Bean是要用来导出的自定义实体类ExcelUtils.export(Bean.class, list, DateUtil.format(new Date(),DateUtil.INT_STRING_FORMAT), response);
源码
ExcelUtils.java
package com.demo.util;import com.andacx.core.log.LogFactory;import com.andacx.tool.Asserts;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.hssf.util.HSSFColor;import org.apache.poi.ss.usermodel.*;import org.apache.poi.ss.util.CellUtil;import org.apache.poi.xssf.streaming.SXSSFSheet;import org.apache.poi.xssf.streaming.SXSSFWorkbook;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.slf4j.Logger;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.lang.reflect.Field;import java.util.*;/** *@description:【Excel写入和导出工具】
*@author:【Boomer】
*@date:【2018/1/11 11:18】
**/public class ExcelUtils { private static final Logger LOGGER = LogFactory.get(ExcelUtils.class); /*** 总行数 **/ private int totalRows = 0; /*** 总条数 **/ private int totalCells = 0; /*** 数据读取开始索引 **/ private int dataReadIndex = 3; /*** 字段名读取开始索引 **/ private int fieldReadIndex = 2; public ExcelUtils() { } public int getTotalRows() { return totalRows; } public int getTotalCells() { return totalCells; } public int getDataReadIndex() { return dataReadIndex; } public void setDataReadIndex(int dataReadIndex) { this.dataReadIndex = dataReadIndex; } public int getFieldReadIndex() { return fieldReadIndex; } public void setFieldReadIndex(int fieldReadIndex) { this.fieldReadIndex = fieldReadIndex; } /** *Description:【验证EXCEL文件】
*Author:【Boomer】
*Date:【2018/1/11 14:07】
* @param filePath * @return **/ public boolean validateExcel(String filePath) { Asserts.notNull(filePath, "文件名不是excel格式"); Asserts.isTrue((isExcel2003(filePath) || isExcel2007(filePath)), "文件名不是excel格式"); return true; } /** *Description:【是否是2003的excel,返回true是2003】
*Author:【Boomer】
*Date:【2018/1/11 14:07】
* @param filePath * @return **/ public static boolean isExcel2003(String filePath) { return filePath.matches("^.+.(xls)$"); } /** *Description:【是否是2007的excel,返回true是2007】
*Author:【Boomer】
*Date:【2018/1/11 14:07】
* @param filePath * @return **/ public static boolean isExcel2007(String filePath) { return filePath.matches("^.+.(xlsx)$"); } /** *Description:【读EXCEL文件,获取客户信息集合】
*Author:【Boomer】
*Date:【2018/1/11 14:07】
* @param fileName * @param Mfile * @return **/ public List
map转实体工具类
package com.andacx.lbs.util;import com.andacx.tool.StringUtil;import org.apache.commons.collections.MapUtils;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * Created by Boomer on 2017/5/19. * @author Boomer */public class MapToBeanUtils { /** * 获取类类型的所有Field包括父类中的Field * * @param clazz 类类型 * @return 返回类类型的所有Field包括父类中的Field */ public static Field[] getAllFields(Class clazz) { Mapmap = new HashMap (); for (Field field : clazz.getDeclaredFields()) { Class fieldType = field.getType(); String fieldName = field.getName(); if(isBaseType(fieldType)){ try { map.put(fieldName, field); } catch (Exception e) { e.printStackTrace(); } } } while (clazz.getSuperclass() != null) { clazz = clazz.getSuperclass(); if (clazz == Object.class) { break; } for (Field field : clazz.getDeclaredFields()) { if (!map.containsKey(field.getName())) { map.put(field.getName(), field); } } } return map.values().toArray(new Field[map.size()]); } /** * Description:【判断是否是基本类型】
*Author:【Boomer】
*Date:【2018/1/8 16:13】
* @param fieldType * @return **/ public static Boolean isBaseType(Class fieldType){ if (fieldType == String.class) { return true; } else if (fieldType == double.class || fieldType == Double.class) { return true; } else if (fieldType == int.class || fieldType == Integer.class) { return true; } else if (fieldType == Boolean.class || fieldType == boolean.class) { return true; } else if (fieldType == Date.class) { return true; } return false; } /** *Description:【将首字母转换为大写】
*Author:【Boomer】
*Date:【2018/1/5 15:54】
* * @param a * @return **/ public static String firstCharToUpper(String a) { return (new StringBuilder()).insert(0, a.substring(0, 1).toUpperCase()).append(a.substring(1)).toString(); } /** *Description:【将map隐射到实体类】
*Author:【Boomer】
*Date:【2018/1/5 16:27】
* * @param map * @param model * @return **/ public staticT getModel(Map map, Class model) { Field[] fields = getAllFields(model); String value; Method method; T obj; try { obj = model.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } for (Field field : fields) { int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { continue; } //根据传入的获取str来判断用哪个字符串获取参数 value = MapUtils.getString(map, field.getName()); if (StringUtil.isEmpty(value)) { if (field.getType() == String.class) { try { method = model.getMethod("get" + firstCharToUpper(field.getName())); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e) { if (field.getType() == Boolean.class || field.getType() == boolean.class) { try { String fieldName = field.getName(); method = model.getMethod("get" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName)); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e1) { System.out.println(e1.getMessage()); } } else { System.out.println(e.getMessage()); } } } } if (StringUtil.isNotEmpty(value)) { invokeMethod(model, obj, value, field.getName(), field.getType()); } } return obj; } /** * Description:【调用方法】
*Author:【Boomer】
*Date:【2018/1/5 16:26】
* * @param modelClass * @param object * @param value * @param fieldName * @param fieldType * @return **/ private staticvoid invokeMethod(Class modelClass, T object, String value, String fieldName, Class fieldType) { Method method = null; try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName), fieldType); } catch (NoSuchMethodException e) { if (fieldType == Boolean.class || fieldType == boolean.class) { try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName), fieldType); } catch (NoSuchMethodException e1) { } } else { } } try { if (null != method) { if (fieldType == String.class) { method.invoke(object, value); } else if (fieldType == double.class || fieldType == Double.class) { try { method.invoke(object, Double.parseDouble(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == int.class || fieldType == Integer.class) { try { method.invoke(object, Integer.parseInt(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == Boolean.class || fieldType == boolean.class) { try { method.invoke(object, Boolean.parseBoolean(value)); } catch (Exception e) { e.printStackTrace(); } } else if (fieldType == Date.class) { try { SimpleDateFormat sdf = (value.length() == 10 ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); method.invoke(object, sdf.parse(value)); } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } }}
- 20180122 这个工具也可以用以下方法实现
public staticList mapToBean(List maps, Class obj) throws IllegalAccessException, InstantiationException { List list = new ArrayList<>(); for (Map map : maps) { T module = obj.newInstance(); BeanWrapper wapper = new BeanWrapperImpl(module); for (Map.Entry entry : map.entrySet()) { if (wapper.isWritableProperty(entry.getKey().toString())) { wapper.setPropertyValue(entry.getKey().toString(), entry.getValue().toString()); } } list.add(module); } return list; }
后语
- 源码中可能掺杂一些个人工具类源码,各位可自行更改,不影响功能实现。如果问题请留言。