1. 程式人生 > >Excel匯入操作

Excel匯入操作

在專案開發的過程中,我們經常會用到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);