在项目开发的过程中,我们经常会用到excel 表格的导入导出,刚解决难免会遇到很多问题,我们使用的是J-Excel 封装好的工具,下面就总结一下具体的操作流程.
一:pom.xml中添加依赖
(1)对于SSM 的项目需要在api的POM文件中加入对J-Excel的依赖
<dependency>
<groupId>org.jplus</groupId>
<artifactId>J-Excel</artifactId>
<scope>provided</scope>
</dependency>
在web的POM文件中加入对J-Excel的依赖
<dependency>
<groupId>org.jplus</groupId>
<artifactId>J-Excel</artifactId>
</dependency>
另外有导入功能的,在Web的POM中加入对commons-fileupload的依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
如果有导入的功能,则在web的spring-mvc.xml中加入:
<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<!-- 指定所上传文件的总大小不能超过10485760000B。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
<property name="maxUploadSize" value="10485760000"></property>
<property name="maxInMemorySize" value="40960"></property>
</bean>
(2)对于springboot 的项目,因为没有springmvc并且集成了multipartResolver.所以直接在该项目的pom文件中添加依赖即可:
<dependency>
<groupId>org.jplus</groupId>
<artifactId>J-Excel</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
二:实体类的配置
1、 加入类注解 @ExcelModelConfig
2、 Excel表格需要导入的字段对应的每个属性加入注解@Lang(value=”属性对应excel表头要导入的名字”)
3、 默认情况下属性值是可以为空的,如果不允许为空,则加入不为空注解。根据不同的数据类型使用不同的注解:
日期型:@InputDateConfig(nullable=false)
字符型:@InputTextConfig(nullable=false)
数字型:@InputIntConfig(nullable=false)
如下式我配置的实体类:
package com.dmsdbj.integral.training.entity;
import com.dmsdbj.cloud.tool.business.BaseEntity;
import lombok.*;
import lombok.experimental.*;
import io.swagger.annotations.*;
import org.jplus.hyberbin.excel.annotation.ExcelModelConfig;
import org.jplus.hyberbin.excel.annotation.Lang;
import org.jplus.hyberbin.excel.annotation.input.InputDicConfig;
import javax.persistence.*;
import java.io.Serializable;
/**
* TrainingProgram实体
* 培养计划项目表
*
* @author 李娜
* @version 0.0.2
* @since 0.0.2 2018-09-18 11:04:05
*/
@ApiModel(value = "TrainingProgramEntity:培养计划项目表")
@Data
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "tit_training_program")
@ExcelModelConfig
public class TrainingProgramEntity extends BaseEntity implements Serializable{
/**
* 项目名称
*/
@Lang(value = "项目名称")
@ApiModelProperty(value = "项目名称")
@Column(name = "name")
private String name;
/**
* 所属等级id
*/
@InputDicConfig(dicCode="levelId")
@ApiModelProperty(value = "所属等级id")
@Column(name = "level_id")
private String levelId;
/**
* 该项目在该等级序列
*/
@Lang(value = "该等级序列")
@ApiModelProperty(value="该等级序列")
@Column(name = "project_order")
private Integer projectOrder;
/**
* 培养计划等级
*/
@Lang(value = "等级")
@ApiModelProperty(value="等级")
@Column(name = "level_order")
private Integer levelOrder;
/**
* 该级别所获得积分
*/
@Lang(value = "该级别所获得积分")
@ApiModelProperty(value = "该级别所获得积分")
@Column(name = "integral")
private Integer integral;
/**
* 项目介绍
*/
@Lang(value = "项目介绍")
@ApiModelProperty(value = "项目介绍")
@Column(name = "description")
private String description;
}
三.在controller中调用J-Excel封装的导入的方法
/**
* 导入excel数据培养计划项目
* @return 导入的结果
* @author 李娜
* @since 0.0.2 2018年10月26日16:26:39
*/
@ResponseBody
@RequestMapping(value={"/importTraining/{file}"},method=RequestMethod.POST)
@ApiOperation(value="导入Excel")
public IntegralResult importTraining(@RequestParam(value="file") MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response){
List<TrainingProgramEntity> trainingList=new ArrayList<>();
//将excel解析成list
if (multipartFile.isEmpty()){
return IntegralResult.build("1111","导入文件为空",null);
}
Map<Serializable,Serializable> map=new HashMap<>(16);
//**sheet的名称*//*
map.put("sheetName","培养计划"); //必须与表格sheet的名称相对应
map.put("Class",TrainingProgramEntity.class);//导入对应的实体类
try{
//读取excel表格数据
trainingList= ExcelUtil.importExcel(multipartFile.getOriginalFilename(),map,request,response);
if(CollectionUtils.isEmpty(trainingList)){
return IntegralResult.build("1111","读取Excel返回结果为空!",null);
}else
{
//查询出所有的等级
IntegralResult<LevelModel> LevelResult=queryAllLevel();
String levelList= JsonUtil.beanToJson(LevelResult.getData(), true);
//将查询出来的级别转化成需要的list的类型
Gson gson=new Gson();
ArrayList<LevelModel> list = new ArrayList<LevelModel>();
Type listType = new TypeToken<List<LevelModel>>() {}.getType();
list = gson.fromJson(levelList, listType);
//将查询出来的级别循环放入Map中, key为LevelOrderId级别,value为levelId即级别对应的id
Map<Integer,String> levelMap=new HashMap<>();
for(LevelModel level:list){
levelMap.put(level.getLevelOrderId(),level.getId());
}
//为表格中每个实体对象添加上levelId
for(TrainingProgramEntity training: trainingList){
if(levelMap.containsKey(training.getLevelOrder())){
training.setLevelId(levelMap.get(training.getLevelOrder()));
}
}
//批量导入培养计划数据
Iterable<TrainingProgramEntity> training=trainingProgramService.insert(trainingList);
return IntegralResult.build("0000","操作成功",training);
}
}catch(Exception e){
log.error("Excel导入异常", e);
return IntegralResult.build("1111", "操作异常,请重新导入");
}
}
这样就可以把excel导入到数据库中了
导入操作遇到的问题:
1.获取sheetname 报NullException
原因:
//**sheet的名称*//*
map.put("sheetName","培养计划"); //必须与表格sheet的名称相对应
map.put("Class",TrainingProgramEntity.class);//导入对应的实体类
在这里给sheetName赋值,在源码中会根据sheetName 来获取要解析的表格,但是我传入的表格中sheetName不是培养计划,这样的话就会报NullExcption了
2.Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path
返回的数据解析错误
IntegralResult<LevelModel> LevelResult=queryAllLevel();
//返回Object类型强转成List 类型
List<LevelModel> list= (List)LevelResult.getData();
Map<Integer,String> levelMap=new HashMap<>();
//将查询出来的级别循环放入Map中, key为LevelOrderId级别,value为levelId即级别对应的id
for(LevelModel level:list){
levelMap.put(level.getLevelOrderId(),level.getId());
}
当执行到for(LevelModel level:list)时就会报错.
java.util.LinkedHashMap cannot be cast to com.dmsdbj.integral.kernel.api.model.LevelModel 或
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path
原因:返回数据解析错误,没有转换成我们期望的list类型
解决办法:
用 TypeToken 转一下
//查询出所有的等级
IntegralResult<LevelModel> LevelResult=queryAllLevel();
String levelList= JsonUtil.beanToJson(LevelResult.getData(), true);
//将查询出来的级别转化成需要的list的类型
Gson gson=new Gson();
ArrayList<LevelModel> list = new ArrayList<LevelModel>();
Type listType = new TypeToken<List<LevelModel>>() {}.getType();
list = gson.fromJson(levelList, listType);