• EasyExcel使用笔记


    官方Github地址:https://github.com/alibaba/easyexcel

    官方使用说明:https://alibaba-easyexcel.github.io/index.html

    使用步骤:

    1. 在页面上新增导入按钮和文件选择框,代码参考:
      <a id="btnImport" class="easyui-linkbutton" data-options="iconCls:'icon-save'" onclick="selectFile()" style="float: right;">导入</a>
      <input id="filebox" name="filebox" type="file" onchange="uploadFile()" style="float:right;display:none;" />
    2. 加入JavaScript方法调用后台,代码参考:
       1     function selectFile(){
       2         $("#filebox").click();
       3     }
       4     function uploadFile() {
       5         if(isLowerIE10()){
       6             $.messager.alert('错误', "当前浏览器版本太低,请使用IE10及以上或者其他浏览器",'error');
       7         } else {
       8             var file = $("#filebox").val();    
       9              if (file.endWith(".xlsx")) {
      10                 var options = {
      11                     type : 'post',
      12                     url : "upload.do",
      13                     dataType : 'json',
      14                     complete : function(result) {
      15                         $('#dg').datagrid("loaded");
      16                         var result = result.responseJSON;
      17                         $.messager.alert('操作提示', result.msg,'info',function(){
      18                             $('#dg').datagrid('reload');
      19                         });
      20                     }
      21                 }
      22                 $('#dg').datagrid("loading");
      23                 $("#searchForm").ajaxSubmit(options);
      24             } else {
      25                 $.messager.alert('错误', "请选择Excel2007以上版本文件,扩展名:xlsx",'error');
      26             }
      27         }
      28     }
      Javacript方法
    3. 后台控制器Controller中接受文件流并传给业务层做进一步处理,代码参考
          @RequestMapping("upload.do")
          @ResponseBody
          public Result upload(HttpServletRequest req, @RequestParam(value = "filebox") MultipartFile file) {
              Result result = Result.getInstanceError();
              try {
                  result = prodlineBugService.importByExcel(file);
              } catch (Exception e) {
                  log.error("产线不良Excel导入异常:", e);
                  result.setMsg(e.getMessage());
              }
              return result;
          }
    4. 业务层service
      public Result importByExcel(MultipartFile file) throws IOException {
              EasyExcel.read(file.getInputStream(), ProdlineBugVO.class, new ProdlineBugListener(this)).sheet().autoTrim(true)
                      .doRead();
              return Result.getInstanceSuccess();
          }
    5. 业务对象VO用注解标识一下列名。
        1 @ExcelIgnoreUnannotated
        2 public class ProdlineBugVO {
        3 
        4     /**
        5      * ID
        6      */
        7     @ExcelProperty(value = "ID")
        8     private Long id;
        9     /**
       10      * 期间(yyyy-mm)
       11      */
       12     private String yearMonth;
       13     /**
       14      * 供应商编码
       15      */
       16     @ExcelProperty(value = "供应商编码")
       17     private String supplierCode;
       18     /**
       19      * 物料编码
       20      */
       21     @ExcelProperty(value = "物料编码")
       22     private String itemNumber;
       23     /**
       24      * 包含Y 不包含N
       25      */
       26     @ExcelProperty(value = "不良数")
       27     private BigDecimal bugNum;
       28     /**
       29      * 总数
       30      */
       31     private BigDecimal totalNum;
       32     /**
       33      * 包含Y 不包含N
       34      */
       35     @ExcelProperty(value = "工单号")
       36     private String icmoCode;
       37     /**
       38      * 描述
       39      */
       40     @ExcelProperty(value = "描述")
       41     private String description;
       42     /**
       43      * 季度考核ID
       44      */
       45     private Long quarterExamineId;
       46     /**
       47      * 发生时间
       48      */
       49     @ExcelProperty(value = "发生日期")
       50     private Date actualTime;
       51 
       52     private String itemName;
       53     private String supplierName;
       54     /** excel行号 */
       55     private Integer rowIndex;
       56 
       57     /**
       58      * 设置 ID
       59      */
       60     public Long getId() {
       61         return id;
       62     }
       63 
       64     /**
       65      * 获取 ID
       66      */
       67     public void setId(Long id) {
       68         this.id = id;
       69     }
       70 
       71     /**
       72      * 设置 期间(yyyy-mm)
       73      */
       74     public String getYearMonth() {
       75         return yearMonth;
       76     }
       77 
       78     /**
       79      * 获取 期间(yyyy-mm)
       80      */
       81     public void setYearMonth(String yearMonth) {
       82         this.yearMonth = yearMonth;
       83     }
       84 
       85     /**
       86      * 设置 供应商编码
       87      */
       88     public String getSupplierCode() {
       89         return supplierCode;
       90     }
       91 
       92     /**
       93      * 获取 供应商编码
       94      */
       95     public void setSupplierCode(String supplierCode) {
       96         this.supplierCode = supplierCode;
       97     }
       98 
       99     /**
      100      * 设置 物料编码
      101      */
      102     public String getItemNumber() {
      103         return itemNumber;
      104     }
      105 
      106     /**
      107      * 获取 物料编码
      108      */
      109     public void setItemNumber(String itemNumber) {
      110         this.itemNumber = itemNumber;
      111     }
      112 
      113     public BigDecimal getBugNum() {
      114         return bugNum;
      115     }
      116 
      117     public void setBugNum(BigDecimal bugNum) {
      118         this.bugNum = bugNum;
      119     }
      120 
      121     public BigDecimal getTotalNum() {
      122         return totalNum;
      123     }
      124 
      125     public void setTotalNum(BigDecimal totalNum) {
      126         this.totalNum = totalNum;
      127     }
      128 
      129     /**
      130      * 设置 包含Y 不包含N
      131      */
      132     public String getIcmoCode() {
      133         return icmoCode;
      134     }
      135 
      136     /**
      137      * 获取 包含Y 不包含N
      138      */
      139     public void setIcmoCode(String icmoCode) {
      140         this.icmoCode = icmoCode;
      141     }
      142 
      143     /**
      144      * 设置 描述
      145      */
      146     public String getDescription() {
      147         return description;
      148     }
      149 
      150     /**
      151      * 获取 描述
      152      */
      153     public void setDescription(String description) {
      154         this.description = description;
      155     }
      156 
      157     /**
      158      * 设置 季度考核ID
      159      */
      160     public Long getQuarterExamineId() {
      161         return quarterExamineId;
      162     }
      163 
      164     /**
      165      * 获取 季度考核ID
      166      */
      167     public void setQuarterExamineId(Long quarterExamineId) {
      168         this.quarterExamineId = quarterExamineId;
      169     }
      170 
      171     /**
      172      * 设置 发生时间
      173      */
      174     public Date getActualTime() {
      175         return actualTime;
      176     }
      177 
      178     /**
      179      * 获取 发生时间
      180      */
      181     public void setActualTime(Date actualTime) {
      182         this.actualTime = actualTime;
      183     }
      184 
      185     /**
      186      * 创建人(邮箱)
      187      */
      188     private String createBy;
      189     /**
      190      * 创建时间
      191      */
      192     private Date createTime;
      193     /**
      194      * 更新人(邮箱)
      195      */
      196     private String updateBy;
      197     /**
      198      * 更新时间
      199      */
      200     private Date updateTime;
      201 
      202     public String getCreateBy() {
      203         return createBy;
      204     }
      205 
      206     public void setCreateBy(String createBy) {
      207         this.createBy = createBy;
      208     }
      209 
      210     public Date getCreateTime() {
      211         return createTime;
      212     }
      213 
      214     public void setCreateTime(Date createTime) {
      215         this.createTime = createTime;
      216     }
      217 
      218     public String getUpdateBy() {
      219         return updateBy;
      220     }
      221 
      222     public void setUpdateBy(String updateBy) {
      223         this.updateBy = updateBy;
      224     }
      225 
      226     public Date getUpdateTime() {
      227         return updateTime;
      228     }
      229 
      230     public void setUpdateTime(Date updateTime) {
      231         this.updateTime = updateTime;
      232     }
      233 
      234     public String getItemName() {
      235         return itemName;
      236     }
      237 
      238     public void setItemName(String itemName) {
      239         this.itemName = itemName;
      240     }
      241 
      242     public String getSupplierName() {
      243         return supplierName;
      244     }
      245 
      246     public void setSupplierName(String supplierName) {
      247         this.supplierName = supplierName;
      248     }
      249 
      250     public Integer getRowIndex() {
      251         return rowIndex;
      252     }
      253 
      254     public void setRowIndex(Integer rowIndex) {
      255         this.rowIndex = rowIndex;
      256     }
      257 }
      View Code
    6. 定义好Listener来调用保存方法。
       1 public class ProdlineBugListener extends AnalysisEventListener<ProdlineBugVO> {
       2     private Logger log = LoggerFactory.getLogger(this.getClass());
       3     
       4     /** 一次处理的数量,防止一次处理的过多造成oom */
       5     private static final int BATCH_COUNT = 5000;
       6     
       7     List<ProdlineBugVO> list = new ArrayList<ProdlineBugVO>();
       8     
       9     private ProdlineBugService prodlineBugService;
      10     
      11     public ProdlineBugListener() {
      12     }
      13 
      14     public ProdlineBugListener(ProdlineBugService prodlineBugService) {
      15         this.prodlineBugService = prodlineBugService;
      16     }
      17     
      18     @Override
      19     public void invoke(ProdlineBugVO data, AnalysisContext context) {
      20         data.setRowIndex(context.readRowHolder().getRowIndex() + 1);
      21         list.add(data);
      22         if (list.size() >= BATCH_COUNT) {
      23             // 达到BATCH_COUNT再处理,防止内存中存储过大数据,容易OOM
      24             prodlineBugService.batchSave(list);
      25             list.clear();
      26         }
      27     }
      28 
      29     @Override
      30     public void doAfterAllAnalysed(AnalysisContext arg0) {
      31         // 这里也要保存数据,确保最后遗留的和不到batch_count的数据也存储到数据库
      32         prodlineBugService.batchSave(list);
      33     }
      34 }
      View Code

    注意事项

    1. 事务问题:如果不想Excel处理过程中被分成好多比事务,那请将读Excel的方法写到有事务控制的业务层。这样,当某一行内容校验失败,抛出异常,前面的操作就会回滚。
    2. 对于日期格式,可以用Date来接收。框架默认已经支持很多常用的数字格式,例如:"yyyy-MM-dd"等,但如果没有解析成功,那就需要使用@DateTimeFormat("yyyy年MM月dd日")注解配置
    3. @ExcelProperty注解支持按列名或列索引来配置表头,如果使用列名的方式,那即使列顺序变更也不会影响读数据。但千万不要2种方式同时配置
    4. 对于少数Excel单元格内容格式不确定的情况(比如动态内容导入)。可能无法定义明确的VO值对象,可以使用Map<Integer, Object>来接受行内容。key是列索引。
      1. 如果单元格内容为空,map中不会有这个单元格对应的Entry,所以不要用EntrySet来循环
      2. 可以一开始就记录好表头的列数量,然后用这个列数量来循环Map,这样就知道哪一列是空的了。
    5. 如果Excel中有空行,框架会自动跳过不会调用invoke方法。
    6. autoTrim如果是true,读单元格内容时会自动trim。
    7. 框架默认第一行是表头,数据是从第二行开始的。如果不是可以使用headRowNumber方法指定。
    8. 该框架已经解决了POI头疼的性能问题而且简化了很多Excel读写的代码。更多功能可以参考官方github
  • 相关阅读:
    python 基础第二篇
    python 基础第五篇
    python 基础第四篇
    购物小编程(完整编码)
    计算机 python概论
    str 相关操作
    python 基础第三篇
    Nginx 配置多站点vhost
    h5页面宽度设置7.5rem
    js 倒计时,转义
  • 原文地址:https://www.cnblogs.com/namelessmyth/p/12334551.html
Copyright © 2020-2023  润新知