Loading

Excel文件处理工具类(基于EasyExcel)

package com.paasit.pai.core.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;
import com.paasit.pai.core.bean.SystemMessage;
import com.paasit.pai.core.exception.BizLogicException;
import lombok.extern.slf4j.Slf4j;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
* 描述: [com.paasit.pai.core.util][Excel处理工具类]
*
* @version: 0_1
* @author: 朱安泰
* @date: 2022-07-18 16:59
*
* 基于EasyExcel的工具类,在使用时需要先将excel实体类中的字段使用@ExcelProperty来指定表头
**/
@Slf4j
public class EasyExcelAlibabaUtil {
    
    private static final String TAG = "EasyExcelAlibabaUtil";
    
    /**
    * 将excel文件转化成javaList集合,
    * 需要在传入的class的字段中加入EasyExcel的专用注解来指定表名
    * @param excelFile 前端传入的文件
    * @param clazz 一个Class对象
    * @param <T>
    * @return 可以直接转成传入的Class的List集合
    */
    public static <T> List<T> excelToList(MultipartFile excelFile, Class<T> clazz) {
        List<T> objects = null;
        try {
            InputStream inputStream = excelFile.getInputStream();
            objects = EasyExcel.read(inputStream).head(clazz).sheet().doReadSync();
        } catch (Exception e) {
            log.error("excelToList-exception", e);
        } finally {
            return objects;
        }
    }
    
    
    /**
    * 获取excel表头
    * @param excelFile
    * @return
    */
    public static List<String> getColumnNameList(MultipartFile excelFile) throws IOException {
        List<String> columnNameList = new ArrayList<>();
        LinkedHashMap<Integer,String> columnNames = (LinkedHashMap<Integer, String>) EasyExcel.read(excelFile.getInputStream()).sheet().headRowNumber(0).doReadSync().get(0);
        for (Map.Entry<Integer, String> entry : columnNames.entrySet()) {
            Integer key = entry.getKey();
            columnNameList.add(columnNames.get(key));
        }
        log.debug("{}读取到的表头:{}",TAG,columnNameList);
        return columnNameList;
    }
    
    
    /**
    * 检查指定列是否存在
    * @param excelFile
    * @param columnNames
    * @return
    */
    public static void checkExcelColumn(MultipartFile excelFile,List<String> columnNames,StringBuffer errorMsg) throws IOException {
        log.debug("{}开始检查表头内容是否正确,指定表头{}",TAG,columnNames);
        List<String> columnNameList = getColumnNameList(excelFile);
        for (String columnName : columnNames) {
            if (!columnNameList.contains(columnName)){
                errorMsg.append(String.format("<br>在文件中没有找到[%s]列,请检查!",columnName));
            }
        }
    }
    
    
    /**
    * 校验字符串是否仅为字母或数字
    * @param str
    * @return
    */
    public static boolean isLetterDigit(String str) { String regex = "^[a-z0-9A-Z]+$";  return str.matches(regex);}
    
    
    /**
    * 校验excel中是否存在重复数据
    * @param list 校验对象需重写 hashCode与equals方法
    * @return
    */
    public static void isContainsDuplicate(List list,StringBuffer errorMsg){
        for (int i = 0; i < list.size(); i++) {
            Object ti = list.get(i);
            for (int j = i+1; j < list.size(); j++) {
                Object tj = list.get(j);
                if(ti.equals(tj)){
                    errorMsg.append(String.format("<br>第[%s]行与第[%s]行数据内容相同,请检查!",i+1,j+1));
                }
            }
        }
    }
    
    
    /**
    * 读取excel,这个相当于一个高性能模式。
    * 比上面的方法多了一个readListener接口, 需要传一个实现这个接口的实现类
    * 其中invoke方法是每读取一行都会调用, 所以可以读取一行处理一行, 性能比较高。
    * @param excelFile
    * @param clazz
    * @param readListener
    */
    public static void readExcelHighPerformance(MultipartFile excelFile, Class<T> clazz, ReadListener readListener) {
        try {
            InputStream inputStream = excelFile.getInputStream();
            EasyExcel.read(inputStream, clazz, readListener).sheet().doRead();
        } catch (Exception e) {
            log.error("excelToList-readExcelHighPerformance", e);
        }
    }
    
    /**
    * 下载excel
    * @param response web项目中response对象
    * @param clazz Class对象, 需要读取这个Class中的字段注解的名称, 用于生成表头
    * @param list  java的List集合,需要与传入的Class匹配
    * @param excelName 需要生成的excel名称
    */
    public static void download(HttpServletResponse response, Class<?> clazz, List<?> list, String excelName) {
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                               "attachment;filename=" + URLEncoder.encode(excelName, "UTF-8"));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            EasyExcel.write(baos, clazz).sheet("sheet1").doWrite(list);
            response.setHeader("Content-Length", String.valueOf(baos.size()));
            outputStream.write(baos.toByteArray());
            response.flushBuffer();
        } catch(Exception e){
            log.error("excelToList-download", e);
        }
    }
    
    
    /**
    * 文件类型检验
    * @param file
    * @throws BizLogicException
    */
    public static void checkFile(MultipartFile file) throws BizLogicException {
        // 判断文件是否存在
        if (null == file) {
            throw  new BizLogicException(new SystemMessage("FileNotExist","文件不存在"));
        }
        // 获得文件名
        String fileName = file.getOriginalFilename();
        // 判断文件是否是excel文件
        if (!fileName.endsWith("xls") && !fileName.endsWith("xlsx")) {
            throw new BizLogicException(new SystemMessage("FileTypeError","文件类型错误"));
            
        }
    }
    
    /**
    * 属性规则校验 (需要在对象上使用 Validator 注解)
    * @param list
    * @return
    */
    public static void checkObjectParam(List list,StringBuffer errorMsg)  {
        for (int i = 0; i < list.size(); i++) {
            String s = ValidatorUtils.validateEntity(list.get(i));
            if (StringUtils.isNotBlank(s)){
                errorMsg.append(String.format("<br>第[%s]行,%s",i+1,s));
            }
        }
    }
}


package com.paasit.pai.core.util;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Iterator;
import java.util.Set;

/**
 * 描述: [com.paasit.pai.core.util][对象属性校验工具类]
 *
 * @version: 0_1
 * @author: 朱安泰
 * @date: 2022-07-19 13:19
 **/
public class ValidatorUtils {
    private ValidatorUtils() { }

    private static Validator validator;
    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    /**
     * 校验对象
     * @param object 待校验对象
     * @param groups 待校验的组
     */
    public static String validateEntity(Object object, Class<?>... groups) {
        StringBuilder msg = new StringBuilder();
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            Iterator<ConstraintViolation<Object>> iterator = constraintViolations.iterator();
            while (iterator.hasNext()) {
                ConstraintViolation<Object> constraint = iterator.next();
                msg.append(constraint.getMessage());
            }
        }
        return msg.toString();
    }
}
posted @ 2022-07-24 23:08  ANTIA11  阅读(676)  评论(0编辑  收藏  举报