1 介绍

excel导入工具

整个项目的代码结构如下

    \---excelExport # 导出工具包
| AsyncExportExcel.java #多线程导出
| ExcelImport.java # 导出工具类
|
+---data
| BaseParam.java # 基础导出参数类
|
+---dataConversion
| DataExportConversion.java # 属性导出转换接口
|
+---defaultDataHandle # 默认的数据处理
| AbstractDataHandler.java
| BooleanDataHandler.java
| DataHandlerFactory.java
| DateDataHandler.java
| StringDataHandler.java
|
\---style # 默认的样式
AbstractCellStyle.java
DefaultDataCellStyle.java
DefaultTitleCellStyle.java com
\---utils
+---demo # 案例相关
| | ExcelImportApplication.java # springboot启动类
| |
| +---bean
| | DemoBean.java # 测试bean
| |
| +---controller
| | ExcelImportController.java # 测试从web导入excel和从文件导入excel
| |
| \---importParam
| | DemoImportParam.java # 导入参数
| |
| \---dataConversion
| HobbyConversion.java # 爱好属性导入转换类
|
\---excelImport # 导入工具包
| ExcelImport.java # 导入工具类
|
+---data
| CellParam.java # 导入列参数类
|
\---dataConversion
| DataImportConversion.java # 属性导入转换接口
|
\---impl
DateConversion.java # 日期属性导入转换接口
MapConversion.java # 键值对属性导入转换接口

简单的来说excel导入可以分为几步

  1. 上传excel文件
  2. 将excel转换为数据,有需要的数据进行转换

2 使用

2.1 ExcelImport工具类

首先实例化ExcelImport工具类,我这里提供了一个构造函数

public ExcelImport(Class<T> clazz, List<CellParam> cellParams)
参数 含义
clazz Class对象(需要转换为Bean的Class对象)
cellParams CellParam的list列表(每一列对应的字段及数据转换类)

实例化ExcelImport工具类之后,需要调用importExcel方法,方法定义如下

public List<T> importExcel(InputStream is)

只需要传入InputStream即可。

2.2 导入列参数类CellParam

CellParam类代码如下

public class CellParam {
private String fieldName;
private DataImportConversion conversion; //Set Get Constructor
}

2.2.1 属性

可以看到CellParam类有两个属性

private String fieldName;
private DataImportConversion conversion;
参数 含义
fieldName 列对应Bean的属性
conversion 数据转换类

2.3 数据转换接口DataImportConversion

public interface DataImportConversion<T> {
T transferData(Object data);
}

我这里默认提供了两种数据转换,一个是键值对,另一个是日期

2.3.1 键值对数据转换

键值对数据转换类是为了将一些通用数据转换而提供的。

例如:男女、是否和一些不同名称对应的不同数字(正常-->0,异常-->1,其他-->2)

使用者可以通过传入的map的泛型决定返回值的类型。

public class MapConversion<K,V> implements DataImportConversion<V> {

    private Map<K,V> map ;

    private V defaultReturnValue;

    public MapConversion(Map<K, V> map) {
this(map,null);
} public MapConversion(Map<K, V> map,V defaultReturnValue) {
this.map = map;
this.defaultReturnValue = defaultReturnValue;
} @Override
public V transferData(Object data) {
if (map == null) return null; //如果data为null且map的null对应的值不为null,则直接返回map中null对应的值
if (data == null && map.get(null) != null){
return map.get(null);
} //循环查找对应的key
for (Map.Entry<K,V> entry:map.entrySet()){
if (entry.getKey() != null && entry.getKey().equals(data)){
return entry.getValue();
}
}
//如果map里面找不到对应的数据,则返回defaultReturnValue
return defaultReturnValue;
}
}

2.3.2 日期数据转换

提供日期转换功能,通过传入的日期转换格式进行转换。

public class DateConversion implements DataImportConversion<Date> {
private SimpleDateFormat format; public DateConversion(String pattern) {
this.format = new SimpleDateFormat(pattern);
} @Override
public Date transferData(Object data) {
try {
return format.parse(data.toString());
} catch (Exception e){
e.printStackTrace();
} return null;
}
}

3 案例

3.1 场景

原始数据如下

姓名 性别 出生日期 爱好
尘心 2018-08-08 14:59:11 舞刀,弄枪
千月 2018-08-08 14:59:11 唱歌,跳舞

需要转换为实体bean的列表,如下

DemoBean{name='尘心', sex=0, birthday=Wed Aug 08 14:13:45 CST 2018, hobbies=[舞刀, 弄枪]}
DemoBean{name='千月', sex=1, birthday=Wed Aug 08 14:13:45 CST 2018, hobbies=[唱歌, 跳舞]}

实体类如下

public class DemoBean {

    //姓名
private String name; //性别,0->女,1->男
private Integer sex; //出生日期
private Date birthday; //爱好
private List<String> hobbies; //Set Get }

3.2 数据转换

可以看到有三个属性需要转换,分别是性别、日期和爱好。性别和日期的数据转换可以使用默认的数据转换。爱好需要将字符串根据分割并转换为list列表数据,下面是爱好的数据转换,

public class HobbyConversion implements DataImportConversion<List<String>> {
@Override
public List<String> transferData(Object data) {
if (data == null) return null; //根据,分割字符串
String hobbyStr = data.toString();
String[] hobbyArray = hobbyStr.split(","); //转换成list
List<String> hobbies = Arrays.asList(hobbyArray);
return hobbies;
}
}

3.3 导入参数类

数据转换类写好了之后,开始编写导入参数类,代码如下

public class DemoImportParam {
public static List<CellParam> getCellParams(){
Map<String,Integer> sexMap = new HashMap<>();
sexMap.put("女",0);
sexMap.put("男",1); List<CellParam> cellParams = new ArrayList<>();
cellParams.add(new CellParam("name"));
cellParams.add(new CellParam("sex", new MapConversion(sexMap)));
cellParams.add(new CellParam("birthday", new DateConversion("yyyy-MM-dd HH:mm:ss")));
cellParams.add(new CellParam("hobbies", new HobbyConversion()));
return cellParams;
}
}

在DemoImportParam类中可以看到一个静态方法getCellParams,返回List。方法内部先定义了一个mao对象,存放性别字符串对应的数字,然后就是List的定义。

可以看到总共有4个列参数

  • 第一列标题名称为姓名,对应的属性名称为name
  • 第二列标题名称为性别,对应的属性名称为sex,数据转换对象MapConversion
  • 第三列标题名称为出生日期,对应的属性名称为birthday,日期转换
  • 第四列标题名称为爱好,对应的属性名称为hobbies,数据转换对象HobbyConversion

3.4 导出

接下来有两种数据导出方式,一种是url访问弹出下载excel文件,另外一种是导出excel到文件

3.4.1 从web导入excel

@ResponseBody
@PostMapping("/import")
public List<DemoBean> importByWeb(MultipartFile file) throws Exception {
ExcelImport excelImport = new ExcelImport(DemoBean.class, DemoImportParam.getCellParams());
List<DemoBean> list = excelImport.importExcel(file.getInputStream()); return list;
}

3.4.2 从文件导入excel

@Test
public void importByFile() throws Exception {
File file = new File("F:\\导出demo.xlsx");
FileInputStream inputStream = new FileInputStream(file); //导入转换
ExcelImport excelImport = new ExcelImport(DemoBean.class, DemoImportParam.getCellParams());
List<DemoBean> list = excelImport.importExcel(inputStream); //输出
for (DemoBean bean:list){
System.out.println(bean);
}
}

项目位置:https://github.com/rainbowda/utils/tree/master/excel_import,有需要的可以看看

最新文章

  1. ServerSocket的介绍
  2. 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray
  3. Caffe源码解析6:Neuron_Layer
  4. 关于yii2框架活动记录activeRecord添加默认字段的问题
  5. KVC/KVO简单实例代码
  6. Font Awesome符号字体
  7. Android 5.x特性概览四
  8. Web 技术人员需知的 Web 缓存知识(转)
  9. 【BZOJ】【1324】王者之剑
  10. POJ 2342 (树形DP)
  11. python学习第八天 -- 迭代
  12. [linux]ubuntu14.04通过apt-get安装软件失败
  13. 剑指offer(纪念版) 面试题3:二维数组中的查找
  14. Mysql数据库的触发程序
  15. js及jsp区别
  16. swiper 父级元素display:none 之bug
  17. Dispatch Queue 之 dispatch_sync
  18. Python3.x使用PyMysql连接MySQL数据库
  19. python 中变量引用问题
  20. jquery遍历指定元素下的img图片改变其路径

热门文章

  1. Python 2.7_爬取CSDN单页面利用正则提取博客文章及url_20170114
  2. Knuth-Morris-Pratt&#160;算法
  3. 设置nodepad++的编码问题
  4. dockerfile mysql
  5. 如何批量清除128组节点db上面的过期的binlog,释放磁盘空间。(转)
  6. Oracle 闪回归档(Flashback Database)
  7. Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之验证码
  8. Python:内置split()方法
  9. Jlink flash 烧录HEX 程序
  10. 基于opencv+ffmpeg的镜头分割