注解+反射优雅的实现Excel导入导出(通用版)

沙海 2021年8月11日12:52:46Java评论44字数 8203阅读27分20秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/40865.html

一般我们在导出的时候都是导出的前端表格,而前端表格同时也会对应的在后台有一个映射类。欢迎加入我的知识星球,一起探讨架构,交流源码。文章源自JAVA秀-https://www.javaxiu.com/40865.html

原文约 4943 | 图片 16 | 建议阅读 10 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)

点击关注 ? Java基基 文章源自JAVA秀-https://www.javaxiu.com/40865.html

收录于话题文章源自JAVA秀-https://www.javaxiu.com/40865.html

#Java基基文章源自JAVA秀-https://www.javaxiu.com/40865.html

299个文章源自JAVA秀-https://www.javaxiu.com/40865.html

点击上方“Java基基”,选择“设为星标”文章源自JAVA秀-https://www.javaxiu.com/40865.html

做积极的人,而不是积极废人!文章源自JAVA秀-https://www.javaxiu.com/40865.html

每天 14:00 更新文章,每天掉亿点点头发...文章源自JAVA秀-https://www.javaxiu.com/40865.html

文章源自JAVA秀-https://www.javaxiu.com/40865.html

源码精品专栏文章源自JAVA秀-https://www.javaxiu.com/40865.html

 文章源自JAVA秀-https://www.javaxiu.com/40865.html

文章源自JAVA秀-https://www.javaxiu.com/40865.html

来源:blog.csdn.net/youzi1394046585/文章源自JAVA秀-https://www.javaxiu.com/40865.html

article/details/86670203文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

日常在做后台系统的时候会很频繁的遇到Excel导入导出的问题,正好这次在做一个后台系统,就想着写一个公用工具来进行Excel的导入导出。文章源自JAVA秀-https://www.javaxiu.com/40865.html

一般我们在导出的时候都是导出的前端表格,而前端表格同时也会对应的在后台有一个映射类。文章源自JAVA秀-https://www.javaxiu.com/40865.html

所以在写这个工具的时候我们先理一下我们需要实现的效果:文章源自JAVA秀-https://www.javaxiu.com/40865.html

  • 导出方法接收一个list集合,和一个Class类型,和HttpServletResponse 对象文章源自JAVA秀-https://www.javaxiu.com/40865.html

  • 导出是可能会有下拉列表,所以需要一个map存储下拉列表数据源,传入参数后只需一行代码即可导出文章源自JAVA秀-https://www.javaxiu.com/40865.html

  • 导入方法需要传入file文件,以及一个Class类型,导入之后将会返回一个list集合,里面的对象就是传入类型的对象,传入参数后只需一行代码即可导入文章源自JAVA秀-https://www.javaxiu.com/40865.html

实现过程:

首先需要创建三个注解文章源自JAVA秀-https://www.javaxiu.com/40865.html

一个是EnableExport ,必须有这个注解才能导出文章源自JAVA秀-https://www.javaxiu.com/40865.html

/** * 设置允许导出 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface EnableExport {     String fileName();}

然后就是EnableExportField,有这个注解的字段才会导出到Excel里面,并且可以设置列宽文章源自JAVA秀-https://www.javaxiu.com/40865.html

/** * 设置该字段允许导出 * 并且可以设置宽度 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface EnableExportField {     int colWidth() default  100;     String colName();}

再就是ImportIndex,导入的时候设置Excel中的列对应的序号文章源自JAVA秀-https://www.javaxiu.com/40865.html

/** * 导入时索引 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ImportIndex {     int index() ;}

注解使用示例文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

推荐下自己做的 Spring Boot 的实战项目:文章源自JAVA秀-https://www.javaxiu.com/40865.html

https://github.com/YunaiV/ruoyi-vue-pro文章源自JAVA秀-https://www.javaxiu.com/40865.html

三个注解创建好之后就需要开始操作Excel了

首先,导入方法。在后台接收到前端上传的Excel文件之后,使用poi来读取Excel文件文章源自JAVA秀-https://www.javaxiu.com/40865.html

我们根据传入的类型上面的字段注解的顺序来分别为不同的字段赋值,然后存入集合中,再返回文章源自JAVA秀-https://www.javaxiu.com/40865.html

代码如下:文章源自JAVA秀-https://www.javaxiu.com/40865.html

/** * 将Excel转换为对象集合 * @param excel Excel 文件 * @param clazz pojo类型 * @return */public static List<Object> parseExcelToList(File excel,Class clazz){    List<Object> res = new ArrayList<>();    // 创建输入流,读取Excel    InputStream is = null;    Sheet sheet = null;    try {        is = new FileInputStream(excel.getAbsolutePath());        if (is != null) {            Workbook workbook = WorkbookFactory.create(is);            //默认只获取第一个工作表            sheet = workbook.getSheetAt(0);            if (sheet != null) {             //前两行是标题                int i = 2;                String values[] ;                Row row = sheet.getRow(i);                while (row != null) {                    //获取单元格数目                    int cellNum = row.getPhysicalNumberOfCells();                    values = new String[cellNum];                    for (int j = 0; j <= cellNum; j++) {                        Cell cell =   row.getCell(j);                        if (cell != null) {                            //设置单元格内容类型                            cell.setCellType(Cell.CELL_TYPE_STRING );                            //获取单元格值                            String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();                            values[j]=value;                        }                    }                    Field[] fields = clazz.getDeclaredFields();                    Object obj = clazz.newInstance();                    for(Field f : fields){                        if(f.isAnnotationPresent(ImportIndex.class)){                            ImportIndex annotation = f.getDeclaredAnnotation(ImportIndex.class);                            int index = annotation.index();                            f.setAccessible(true);                            //此处使用了阿里巴巴的fastjson包里面的一个类型转换工具类                            Object val =TypeUtils.cast(values[index],f.getType(),null);                            f.set(obj,val);                        }                    }                    res.add(obj);                    i++;                    row=sheet.getRow(i);                }            }        }    } catch (Exception e) {        e.printStackTrace();    }    return res;}

接下来就是导出方法。文章源自JAVA秀-https://www.javaxiu.com/40865.html

导出分为几个步骤:文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 建立一个工作簿,也就是类型新建一个Excel文件文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 建立一张sheet表文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 设置标的行高和列宽文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 绘制标题和表头文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

这两个方法是自定义方法,代码会贴在后面文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 写入数据到Excel文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 创建下拉列表文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

  1. 写入文件到response文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

到这里导出工作就完成了文章源自JAVA秀-https://www.javaxiu.com/40865.html

推荐下自己做的 Spring Cloud 的实战项目:文章源自JAVA秀-https://www.javaxiu.com/40865.html

https://github.com/YunaiV/onemall文章源自JAVA秀-https://www.javaxiu.com/40865.html

下面是一些自定义方法的代码

/** * 获取一个基本的带边框的单元格 * @param workbook * @return */private static HSSFCellStyle getBasicCellStyle(HSSFWorkbook workbook){    HSSFCellStyle hssfcellstyle = workbook.createCellStyle();    hssfcellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);    hssfcellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);    hssfcellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);    hssfcellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);    hssfcellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);    hssfcellstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);    hssfcellstyle.setWrapText(true);    return hssfcellstyle;}/** * 获取带有背景色的标题单元格 * @param workbook * @return */private static HSSFCellStyle getTitleCellStyle(HSSFWorkbook workbook){    HSSFCellStyle hssfcellstyle =  getBasicCellStyle(workbook);    hssfcellstyle.setFillForegroundColor((short) HSSFColor.CORNFLOWER_BLUE.index); // 设置背景色    hssfcellstyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);    return hssfcellstyle;}/** * 创建一个跨列的标题行 * @param workbook * @param hssfRow * @param hssfcell * @param hssfsheet * @param allColNum * @param title */private static void createTitle(HSSFWorkbook workbook, HSSFRow hssfRow , HSSFCell hssfcell, HSSFSheet hssfsheet,int allColNum,String title){    //在sheet里增加合并单元格    CellRangeAddress cra = new CellRangeAddress(0, 0, 0, allColNum);    hssfsheet.addMergedRegion(cra);    // 使用RegionUtil类为合并后的单元格添加边框    RegionUtil.setBorderBottom(1, cra, hssfsheet, workbook); // 下边框    RegionUtil.setBorderLeft(1, cra, hssfsheet, workbook); // 左边框    RegionUtil.setBorderRight(1, cra, hssfsheet, workbook); // 有边框    RegionUtil.setBorderTop(1, cra, hssfsheet, workbook); // 上边框    //设置表头    hssfRow = hssfsheet.getRow(0);    hssfcell = hssfRow.getCell(0);    hssfcell.setCellStyle( getTitleCellStyle(workbook));    hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);    hssfcell.setCellValue(title);}/** * 设置表头标题栏以及表格高度 * @param workbook * @param hssfRow * @param hssfcell * @param hssfsheet * @param colNames */private static void createHeadRow(HSSFWorkbook workbook,HSSFRow hssfRow , HSSFCell hssfcell,HSSFSheet hssfsheet,List<String> colNames){    //插入标题行    hssfRow = hssfsheet.createRow(1);    for (int i = 0; i < colNames.size(); i++) {        hssfcell = hssfRow.createCell(i);        hssfcell.setCellStyle(getTitleCellStyle(workbook));        hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);        hssfcell.setCellValue(colNames.get(i));    }}/** * excel添加下拉数据校验 * @param sheet 哪个 sheet 页添加校验 * @return */public static void createDataValidation(Sheet sheet,Map<Integer,String[]> selectListMap) {    if(selectListMap!=null) {        selectListMap.forEach(                // 第几列校验(0开始)key 数据源数组value                (key, value) -> {                    if(value.length>0) {                        CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(2, 65535, key, key);                        DataValidationHelper helper = sheet.getDataValidationHelper();                        DataValidationConstraint constraint = helper.createExplicitListConstraint(value);                        DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);                        //处理Excel兼容性问题                        if (dataValidation instanceof XSSFDataValidation) {                            dataValidation.setSuppressDropDownArrow(true);                            dataValidation.setShowErrorBox(true);                        } else {                            dataValidation.setSuppressDropDownArrow(false);                        }                        dataValidation.setEmptyCellAllowed(true);                        dataValidation.setShowPromptBox(true);                        dataValidation.createPromptBox("提示", "只能选择下拉框里面的数据");                        sheet.addValidationData(dataValidation);                    }                }        );    }}

使用实例文章源自JAVA秀-https://www.javaxiu.com/40865.html

导出数据文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

导入数据(返回对象List)文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

图片文章源自JAVA秀-https://www.javaxiu.com/40865.html

源码地址:文章源自JAVA秀-https://www.javaxiu.com/40865.html

https://github.com/xyz0101/excelutils文章源自JAVA秀-https://www.javaxiu.com/40865.html

- END -文章源自JAVA秀-https://www.javaxiu.com/40865.html

欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

已在知识星球更新源码解析如下:文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

注解+反射优雅的实现Excel导入导出(通用版)文章源自JAVA秀-https://www.javaxiu.com/40865.html

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。文章源自JAVA秀-https://www.javaxiu.com/40865.html

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。文章源自JAVA秀-https://www.javaxiu.com/40865.html

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。文章源自JAVA秀-https://www.javaxiu.com/40865.html

文章源自JAVA秀-https://www.javaxiu.com/40865.html

文章有帮助的话,在看,转发吧。谢谢支持哟 (*^__^*)
文章源自JAVA秀-https://www.javaxiu.com/40865.html

阅读原文文章源自JAVA秀-https://www.javaxiu.com/40865.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定