广告
返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot整合EasyExcel实现文件导入导出
  • 532
分享到

SpringBoot整合EasyExcel实现文件导入导出

2024-04-02 19:04:59 532人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录准备工作 1. 引入pom依赖2. 实现功能 excel文件下载 3. 日志实体类4. 接口和具体实现 Excel文件导入 5. 文件读取配置 6. 读取测试7. 附上自定义属性

准备工作

注意:点击查看官网Demo

1. 引入pom依赖


        <!--easyExcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
        </dependency>

2. 实现功能

  • 结合Vue前端,实现浏览器页面直接导出日志文件
  • 实现文件的导入

Excel文件下载

3. 日志实体类

实体类里有自定义转换器:用于Java类型数据和Excel类型数据的转换,非常使用。结合注解,可以非常方便的进行Excel文件导出。



@Data
@EqualsAndHashCode(callSuper = false)
@TableName("tb_operational_log")
@apiModel(value = "OperationalLog对象", description = "操作日志信息")
public class OperationalLog implements Serializable {

    private static final long serialVersionUID = 1L;

    @ExcelProperty({"操作日志", "日志ID"})
    @ApiModelProperty(value = "日志ID")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;

    @ExcelProperty({"操作日志", "操作类型"})
    @ApiModelProperty(value = "操作类型")
    private String operType;

    @ExcelProperty({"操作日志", "操作描述"})
    @ApiModelProperty(value = "操作描述")
    private String operDesc;

    @ExcelProperty({"操作日志", "操作员ID"})
    @ApiModelProperty(value = "操作员ID")
    private String operUserId;

    @ExcelProperty({"操作日志", "操作员名称"})
    @ApiModelProperty(value = "操作员名称")
    private String operUserName;

    @ExcelProperty({"操作日志", "操作方法"})
    @ApiModelProperty(value = "操作方法")
    private String operMethod;

    @ExcelProperty({"操作日志", "请求方法"})
    @ApiModelProperty(value = "请求方法")
    private String operRequWay;

    @ExcelProperty(value = {"操作日志", "请求耗时:单位-ms"}, converter = CustomRequestTimeConverter.class)
    @ApiModelProperty(value = "请求耗时:单位-ms")
    private Long operRequTime;

    @ExcelProperty({"操作日志", "请求参数"})
    @ApiModelProperty(value = "请求参数")
    private String operRequParams;

    @ExcelProperty({"操作日志", "请求Body"})
    @ApiModelProperty(value = "请求Body")
    private String operRequBody;

    @ExcelProperty({"操作日志", "请求IP"})
    @ApiModelProperty(value = "请求IP")
    private String operRequIp;

    @ExcelProperty({"操作日志", "请求URL"})
    @ApiModelProperty(value = "请求URL")
    private String operRequUrl;

    @ExcelProperty(value = {"操作日志", "日志标识"}, converter = CustomLogFlaGConverter.class)
    @ApiModelProperty(value = "日志标识: 1-admin,0-portal")
    private Boolean logFlag;

    @ExcelProperty({"操作日志", "操作状态"})
    @ApiModelProperty(value = "操作状态:1-成功,0-失败")
    @TableField(value = "is_success")
    private Boolean success;

    @ExcelIgnore
    @ApiModelProperty(value = "逻辑删除 1-未删除, 0-删除")
    @TableField(value = "is_deleted")
    @TableLogic(value = "1", delval = "0")
    private Boolean deleted;

    @ExcelProperty(value = {"操作日志", "创建时间"}, converter = CustomTimeFORMatConverter.class)
    @ApiModelProperty(value = "创建时间")
    private Date gmtCreate;
}

4. 接口和具体实现

4.1 接口


    @OperatingLog(operType = BlogConstants.EXPORT, operDesc = "导出操作日志,写出到响应流中")
    @ApiOperation(value = "导出操作日志", hidden = true)
    @PostMapping("/oper/export")
    public void operLogExport(@RequestBody List<String> logIds, httpservletResponse response) {
        operationalLogService.operLogExport(logIds, response);
    }

4.2 具体实现

  • 自定义导出策略HorizontalCellStyleStrategy
  • 自定义导出拦截器CellWriteHandler,更加精确的自定义导出策略

    
    @Override
    public void operLogExport(List<String> logIds, HttpServletResponse response) {
        OutputStream outputStream = null;
        try {
            List<OperationalLog> operationalLogs;
            LambdaQueryWrapper<OperationalLog> queryWrapper = new LambdaQueryWrapper<OperationalLog>()
                    .orderByDesc(OperationalLog::getGmtCreate);
            // 如果logIds不为null,按照id查询信息,否则查询全部
            if (!CollectionUtils.isEmpty(logIds)) {
                operationalLogs = this.listByIds(logIds);
            } else {
                operationalLogs = this.list(queryWrapper);
            }
            outputStream = response.getOutputStream();

            // 获取单元格样式
            HorizontalCellStyleStrategy strategy = MyCellStyleStrategy.getHorizontalCellStyleStrategy();

            // 写入响应输出流数据
            EasyExcel.write(outputStream, OperationalLog.class).excelType(ExcelTypeEnum.XLSX).sheet("操作信息日志")
                    // .reGISterWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽(不是很适应,效果并不佳)
                    .registerWriteHandler(strategy) // 注册上面设置的格式策略
                    .registerWriteHandler(new CustomCellWriteHandler()) // 设置自定义格式策略
                    .doWrite(operationalLogs);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            throw new BlogException(ResultCodeEnum.EXCEL_DATA_EXPORT_ERROR);
        } finally {
            IoUtil.close(outputStream);
        }
    }

自定义导出策略简单如下:




public class MyCellStyleStrategy {

    
    public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
        // 表头策略
        WriteCellStyle headerCellStyle = new WriteCellStyle();
        // 表头水平对齐居中
        headerCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 背景色
        headerCellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        WriteFont headerFont = new WriteFont();
        headerFont.setFontHeightInPoints((short) 14);
        headerCellStyle.setWriteFont(headerFont);
        // 自动换行
        headerCellStyle.setWrapped(Boolean.FALSE);

        // 内容策略
        WriteCellStyle contentCellStyle = new WriteCellStyle();
        // 设置数据允许的数据格式,这里49代表所有可以都允许设置
        contentCellStyle.setDataFormat((short) 49);
        // 设置背景色: 需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        contentCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        contentCellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
        // 设置内容靠左对齐
        contentCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        // 设置字体
        WriteFont contentFont = new WriteFont();
        contentFont.setFontHeightInPoints((short) 12);
        contentCellStyle.setWriteFont(contentFont);
        // 设置自动换行
        contentCellStyle.setWrapped(Boolean.FALSE);
        // 设置边框样式和颜色
        contentCellStyle.setBorderLeft(MEDIUM);
        contentCellStyle.setBorderTop(MEDIUM);
        contentCellStyle.setBorderRight(MEDIUM);
        contentCellStyle.setBorderBottom(MEDIUM);
        contentCellStyle.setTopBorderColor(IndexedColors.RED.getIndex());
        contentCellStyle.setBottomBorderColor(IndexedColors.GREEN.getIndex());
        contentCellStyle.setLeftBorderColor(IndexedColors.YELLOW.getIndex());
        contentCellStyle.setRightBorderColor(IndexedColors.ORANGE.getIndex());

        // 将格式加入单元格样式策略
        return new HorizontalCellStyleStrategy(headerCellStyle, contentCellStyle);
    }
}

自定义导出拦截器简单如下:



public class CustomCellWriteHandler implements CellWriteHandler {

    private static Logger logger = LoggerFactory.getLogger(CustomCellWriteHandler.class);

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                 Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    
    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                       CellData cellData, Cell cell, Head head, Integer relativeRowIndex,
                                       Boolean isHead) {

    }

    
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex,
                                 Boolean isHead) {
        // 设置超链接
        if (isHead && cell.getRowIndex() == 0 && cell.getColumnIndex() == 0) {
            logger.info(" ==> 第{}行,第{}列超链接设置完成", cell.getRowIndex(), cell.getColumnIndex());
            CreationHelper helper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = helper.createHyperlink(HyperlinkType.URL);
            hyperlink.setAddress("https://GitHub.com/alibaba/easyexcel");
            cell.setHyperlink(hyperlink);
        }
        // 精确设置单元格格式
        boolean bool = isHead && cell.getRowIndex() == 1 &&
                (cell.getStringCellValue().equals("请求参数") || cell.getStringCellValue().equals("请求Body"));
        if (bool) {
            logger.info("第{}行,第{}列单元格样式设置完成。", cell.getRowIndex(), cell.getColumnIndex());
            // 获取工作簿
            Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
            CellStyle cellStyle = workbook.createCellStyle();

            Font cellFont = workbook.createFont();
            cellFont.setBold(Boolean.TRUE);
            cellFont.setFontHeightInPoints((short) 14);
            cellFont.setColor(IndexedColors.SEA_GREEN.getIndex());
            cellStyle.setFont(cellFont);
            cell.setCellStyle(cellStyle);
        }
    }
}

4.3 前端请求

前端在基于Vue+Element的基础上实现了点击导出按钮,在浏览器页面进行下载。


// 批量导出
    batchExport() {
      // 遍历获取id集合列表
      const logIds = []
      this.multipleSelection.forEach(item => {
        logIds.push(item.id)
      })
       // 请求后端接口
      axiOS({
        url: this.BASE_API + '/admin/blog/log/oper/export',
        method: 'post',
        data: logIds,
        responseType: 'arraybuffer',
        headers: { 'token': getToken() }
      }).then(response => {
        // type类型可以设置为文本类型,这里是新版excel类型
        const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' })
        const pdfUrl = window.URL.createObjectURL(blob)
        const fileName = 'HorseBlog操作日志' // 下载文件的名字
        // 对于<a>标签,只有 Firefox 和 Chrome(内核)支持 download 属性
        if ('download' in document.createElement('a')) {
          const link = document.createElement('a')
          link.href = pdfUrl
          link.setAttribute('download', fileName)
          document.body.appendChild(link)
          link.click()
          window.URL.revokeObjectURL(pdfUrl) // 释放URL 对象
        } else {
          // IE 浏览器兼容方法
          window.navigator.msSaveBlob(blob, fileName)
        }
      })
    }

测试结果:还行,基本实现了页面下载的功能

Excel文件导入

5. 文件读取配置

本配置基于泛型的方式编写,可扩展性较强。




public class MyExcelImportConfig<T> extends AnalysisEventListener<T> {

    private static Logger logger = LoggerFactory.getLogger(MyExcelImportConfig.class);

    
    private static final int MAX_BATCH_COUNT = 10;

    
    private T dynamicService;

    
    List<T> list = new ArrayList<>();


    
    public MyExcelImportConfig(T dynamicService) {
        this.dynamicService = dynamicService;
    }

    
    @Override
    public void invoke(T data, AnalysisContext context) {
        logger.info(" ==> 解析一条数据: {}", JacksonUtils.objToString(data));
        list.add(data);
        if (list.size() > MAX_BATCH_COUNT) {
            // 保存数据
            saveData();
            // 清空list
            list.clear();
        }
    }

    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        logger.info(" ==> 数据解析完成 <==");
    }

    
    private void saveData() {
        logger.info(" ==> 数据保存开始: {}", list.size());
        list.forEach(System.out::println);
        logger.info(" ==> 数据保存结束 <==");
    }

    
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        logger.error(" ==> 数据解析失败,但是继续读取下一行:{}", exception.getMessage());
        //  如果是某一个单元格的转换异常 能获取到具体行号
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException convertException = (ExcelDataConvertException) exception;
            logger.error("第{}行,第{}列数据解析异常", convertException.getRowIndex(), convertException.getColumnIndex());
        }
    }

}

6. 读取测试


    @ApiOperation(value = "数据导入测试", notes = "操作日志导入测试[OperationalLog]", hidden = true)
    @PostMapping("/import")
    public R excelImport(@RequestParam("file") MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), OperationalLog.class, new MyExcelImportConfig<>(operationalLogService))
                .sheet().doRead();
        return R.ok().message("文件导入成功");
    }

7. 附上自定义属性转换器

转换器的属性内容转换,需要根据自己的实际业务需求而定,这里仅作为简单示例




public class CustomRequestTimeConverter implements Converter<Long> {

    
    @Override
    public Class<Long> supportJavaTypeKey() {
        return Long.class;
    }

    
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    
    @Override
    public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        // 截取字符串: "ms",转换为long类型
        String value = cellData.getStringValue();
        return Long.valueOf(value.substring(0, value.length() - 2));
    }

    @Override
    public CellData<Long> convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        // 添加字符串: "ms"
        return new CellData<>(String.valueOf(value).concat("ms"));
    }
}

格式化时间




public class CustomTimeFormatConverter implements Converter<Date> {

    @Override
    public Class<Date> supportJavaTypeKey() {
        return Date.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String value = cellData.getStringValue();
        return DateUtil.parse(value, DatePattern.NORM_DATETIME_PATTERN);
    }

    @Override
    public CellData<Date> convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData<>(DateUtil.format(value, DatePattern.NORM_DATETIME_PATTERN));
    }
}

EasyExcel简单使用,到此结束,打完收功。

以上就是SpringBoot整合EasyExcel实现文件导入导出的详细内容,更多关于springBoot整合EasyExcel的资料请关注编程网其它相关文章!

--结束END--

本文标题: SpringBoot整合EasyExcel实现文件导入导出

本文链接: https://www.lsjlt.com/news/125098.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot整合EasyExcel实现文件导入导出
    目录准备工作 1. 引入pom依赖2. 实现功能 Excel文件下载 3. 日志实体类4. 接口和具体实现 Excel文件导入 5. 文件读取配置 6. 读取测试7. 附上自定义属性...
    99+
    2022-11-12
  • SpringBoot整合EasyExcel实现导入导出数据
    目录前言1.前端2.数据库3.后端3.1 contrller3.2 mapper3.3 bean3.4 listener3.5 config3.6 配置文件4.启动测试前言...
    99+
    2022-11-13
  • Java+EasyExcel实现文件的导入导出
    目录引言效果图项目结构核心源码核心实体类核心监听器类EasyExcel导入文件EasyExcel导出文件引言 项目中需要Excel文件的导入与导出Excel并下载,例如,导入员工信息...
    99+
    2022-11-12
  • SpringBoot整合EasyExcel实现Excel表格导出功能
    目录栗子1.组件介绍2.配置文件SpringBoot项目pom.xml3.项目代码项目结构ExportController.javaMock.javaCitySheet.javaCo...
    99+
    2022-11-13
  • EasyExcel实现Excel文件导入导出功能
    一、EasyExcel简介 Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的fu...
    99+
    2023-09-15
    excel java Powered by 金山文档
  • Java+EasyExcel如何实现文件的导入导出
    这篇文章将为大家详细讲解有关Java+EasyExcel如何实现文件的导入导出,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。引言项目中需要Excel文件的导入与导出Excel并下载,例如,导入员工信息,导...
    99+
    2023-06-22
  • 使用VUE+SpringBoot+EasyExcel 整合导入导出数据的教程详解
    目录1 前端2 数据库3 后端3.1 contrller3.2 mapper3.3 bean3.4 listener3.5 config3.6 配置文件4 启动测试创建一个普通的ma...
    99+
    2022-11-13
  • Spring Boot + EasyExcel实现数据导入导出
    目录背景SpringBoot项目集成依赖集成实体类实现业务逻辑实现MemberService实现简单导出实现自定义导入实现同步获取结果导入实现基于监听导入实现小结背景 老项目主要采用...
    99+
    2022-11-13
    Spring Boot 数据导入导出 EasyExcel数据导入导出
  • 使用EasyExcel实现Excel的导入导出
    文章目录 前言一、EasyExcel是什么?二、使用步骤1.导入依赖2.编写文件上传配置3.配置表头对应实体类4.监听器编写5.控制层6.前端代码 总结 前言 在真实的开发者场景中,经常会使用excel作为数据的载体,进行...
    99+
    2023-08-17
    java
  • 使用SpringBoot+EasyExcel+Vue实现excel表格的导入和导出详解
    目录一、导入和导出二、导出数据为excel实现过程三、将excel中的数据导入到数据库中一、导入和导出 导入:通过解析excel表格中的数据,然后将数据放到一个集合中,接着通过对持久...
    99+
    2022-11-13
  • java利用easyexcel实现导入与导出功能
    目录前言1先添加依赖2批量插入数据3创建需要导出数据实体类4创建一个类ExcelListener5实现下载excel6控制器添加我们的导入操作代码7导出效果如图8导入直接调用前言 p...
    99+
    2022-11-13
  • 基于EasyExcel实现百万级数据导入导出
    基于EasyExcel实现百万级数据导入导出 在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上。 大数据的导入和...
    99+
    2023-09-12
    java 面试 excel
  • React实现导入导出Excel文件
    目录表示层 业务层 核心插件xlsx excel 导入 excel 导出 excel 导出插件(js-export-excel) 实现效果结语 表示层 这里我是使用的是antd的U...
    99+
    2022-11-12
  • JavaScript实现excel文件导入导出
    目录一、需求场景描述1.此时前端上传解析excel文件可能更合适2.此时前端下载excel文件可能优雅一些二、实现思路分析1.导入excel文件实现思路分析2.导出excel文件实现...
    99+
    2022-11-13
  • 【Java结合EasyExcel,模板文件填充并导出Excel】
    需求描述: 客户网页上填一个Excel表格,数据存到数据库,这个导出接口要做的就是从数据库中的获取数据并填充到模板文件,最后通过response返给前端一个下载链接,用户即可获取填充好的Excel文件。 方案一: 一开始使用的是easypo...
    99+
    2023-09-14
    java
  • Spring Boot 集成 EasyExcel 3.x 优雅实现Excel导入导出
    Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。 🤖 Spring Boot 2.x 实践案例(代码仓库) 介绍...
    99+
    2023-08-22
    spring boot excel java
  • 基于EasyExcel实现百万级数据导入导出详解
    目录1.传统POI的的版本优缺点比较2.使用方式哪种看情况3.百万数据导入导出3.1 模拟500w数据导出3.2模拟500w数据导入4.总结在项目开发中往往需要使用到数据的导入和导出...
    99+
    2023-01-28
    EasyExcel实现数据导入导出 EasyExcel数据导入导出 EasyExcel数据导入 EasyExcel数据导出
  • Springboot实现导入导出Excel的方法
    目录一、添加poi的maven依赖二、自定义注解(Excel属性标题、位置等)三、CustomExcelUtils编写四、定义导出实体类五、Controller层代码编写一、添加po...
    99+
    2022-11-12
  • React怎么实现导入导出Excel文件
    这篇文章主要介绍“React怎么实现导入导出Excel文件”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“React怎么实现导入导出Excel文件”文章能帮助大家解决问题。表示层这里我是使用的是ant...
    99+
    2023-06-05
  • Java怎么实现文件批量导入导出
    本篇内容介绍了“Java怎么实现文件批量导入导出”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、介绍java实现文件的导入导出数据库,目前...
    99+
    2023-06-16
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作