Excel通用导入工具类

利用注解和反射,实现Excel通用导出

注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAnnotation {

    String filedName();

}

导入入参类

在类中属性上方加上先前自定义的注解,标识该列为可导出列,注解中的属性即为导出后的列名

import lombok.Data;

import java.util.Date;

/**
 * @ClassName ExportExcelDto
 * @Author zhang jie
 * @Date 2021/9/22 16:42
 * @Version 1.0
 */
@Data
public class ImportExcelVo{
    @ExcelAnnotation(filedName = "序号")
    @ApiModelProperty("序号")
    private Integer sequenceNumber;

    @ExcelAnnotation(filedName = "题库")
    @ApiModelProperty("所属题库名称")
    private String examName;

    @ExcelAnnotation(filedName = "内容")
    @ApiModelProperty("内容")
    private String content;

    @ExcelAnnotation(filedName = "评分规则")
    @ApiModelProperty("评分规则")
    private String scoringRule;

    @ExcelAnnotation(filedName = "权重")
    @ApiModelProperty("权重")
    private Integer weight;

    @ExcelAnnotation(filedName = "单位")
    @ApiModelProperty("单位")
    private String grpname;

    @ExcelAnnotation(filedName = "是否需要提交材料")
    @ApiModelProperty("是否允许上传材料 中文")
    private String upload;

    @ApiModelProperty("操作用户ID")
    private String operationUserId;

    @ApiModelProperty("创建时间")
    private Date createTime;

    @ApiModelProperty("修改时间")
    private Date updateTime;
}

导入工具类

利用反射获取传入类的所有类名以及类上方所添加的注解,把数据读取出来之后存到list里然后返回

package cn.bywin.assess.base.util;

import cn.bywin.assess.base.annotation.ExcelAnnotation;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * @ClassName ImportExcelUtil
 * @Author zhang jie
 * @Date 2021/8/27 16:01
 * @Version 1.0
 */
public class ImportExcelUtil<T> {

    Class<T> clazz;

    public ImportExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
    }
    public Collection<T> importExcel(MultipartFile file , String...  pattern) {
        Collection<T> dist = new ArrayList<>();
        try {
            /*
             * 类反射得到调用方法
             */
            // 得到目标目标类的所有的字段列表
            Field[] filed = clazz.getDeclaredFields();
            // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
            HashMap<String,Object> map = new HashMap<>();
            // 循环读取所有字段
            for (Field f : filed) {
                // 得到单个字段上的Annotation
                ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
                // 如果标识了Annotation的话
                if (exa != null) {
                    // 构造设置了Annotation的字段的Setter方法
                    String fieldName = f.getName();
                    String setMethodName = "set"
                            + fieldName.substring(0, 1).toUpperCase()
                            + fieldName.substring(1);
                    // 构造调用的method,
                    Method setMethod = clazz.getMethod(setMethodName,
                            f.getType());
                    // 将这个method以Annotation的名字为key来存入。
                    map.put(exa.filedName(), setMethod);
                }
            }
            /*
             * excel的解析开始
             */
            // 将传入的File构造为 FileInputStream;
            File f = new File(Objects.requireNonNull(file.getOriginalFilename()));
            FileCopyUtils.copy(file.getBytes(),f);
            FileInputStream in = new FileInputStream(f);
            // 得到工作表
            HSSFWorkbook book = new HSSFWorkbook(in);
            // 得到第一页
            HSSFSheet sheet = book.getSheetAt(0);
            // 得到第一面的所有行
            Iterator<Row> row = sheet.rowIterator();

            /*
             * 标题解析
             */
            // 得到第一行,也就是标题行
            Row title = row.next();
            // 得到第一行的所有列
            Iterator<Cell> cellTitle = title.cellIterator();
            // 将标题的文字内容放入到一个map中。
            Map<Object,Object> titleMap = new HashMap<>();
            // 从标题第一列开始
            int i = 0;
            // 循环标题所有的列
            while (cellTitle.hasNext()) {
                Cell cell = cellTitle.next();
                String value = cell.getStringCellValue();
                titleMap.put(i, value);
                i = i + 1;
            }
            /*
             * 解析内容行
             */
            //用来格式化日期的 DateFormat
            SimpleDateFormat sf;
            if(pattern.length<1) {
                sf=new SimpleDateFormat("yyyy-MM-dd");
            } else{
                sf=new SimpleDateFormat(pattern[0]);
            }
            while (row.hasNext()) {
                // 标题下的第一行
                Row rows = row.next();
                // 行的所有列
                Iterator<Cell> cellBody = rows.cellIterator();
                // 得到传入类的实例
                T tObject = clazz.newInstance();
                int k = 0;
                // 遍历一行的列
                while (cellBody.hasNext()) {
                    Cell cell = cellBody.next();
                    // 这里得到此列的对应的标题
                    String titleString = (String) titleMap.get(k);
                    // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值
                    if (map.containsKey(titleString)) {
                        Method setMethod = (Method) map.get(titleString);
                        //判断参数类型
                        if (cell.getCellType().equals(CellType.STRING)){
                            setMethod.invoke(tObject, cell.getStringCellValue());
                        }else if (cell.getCellType().equals(CellType.NUMERIC)){
                            setMethod.invoke(tObject, (int) cell.getNumericCellValue());
                        }else if (cell.getCellType().equals(CellType.BOOLEAN)){
                            setMethod.invoke(tObject, cell.getBooleanCellValue());
                        }
                    }
                    // 下一列
                    k = k + 1;
                }
                dist.add(tObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return dist;
    }

    /*
    public static void main(String[] args) {
        ImportExcel<Loginfo> test = new ImportExcel(Loginfo.class);
        File file = new File("D:\\testOne.xls");
        Long befor = System.currentTimeMillis();
        List<Loginfo> result = (ArrayList) test.importExcel(file);

        Long after = System.currentTimeMillis();
        System.out.println("此次操作共耗时:" + (after - befor) + "毫秒");
        // for (int i = 0; i < result.size(); i++) {
        // Loginfo loginfo=result.get(i);
        // System.out.println("导入的信息为:"+loginfo.getLogInfo()+loginfo.getUserip()+loginfo.getUsername());
        // }

        System.out.println("共转化为List的行数为:" + result.size());
    }
     */
}


调用

   ImportExcelUtil<ImportExcelVo> importExcelUtil = new ImportExcelUtil<>(ImportExcelVo.class);
        Collection<ImportExcelVo> importExcelVos = importExcelUtil.importExcel(file);
        ArrayList<ImportExcelVo> list = (ArrayList<ImportExcelVo>) importExcelVos;

结束

ps:另外还有一个通用导出的工具类,实现原理跟这个完全相同,写在另一篇温州

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值