资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

基于EasyExcel的数据导入导出(复制可用)

Java 更新时间: 发布时间: 计算机考试归档 最新发布

基于EasyExcel的数据导入导出(复制可用)

目录

 

前言:

新建SpringBoot项目,引入下面的依赖

数据导入导出执行原理和思路:

用户端逻辑:

后台开发逻辑:

代码实现

下拉框策略

批注策略

数据读取监听

Excel工具类

创建导入数据模板类

创建数据导出模板

Web接口

结果展示

模板下载

数据导入

数据导出


 

前言:

代码复制粘贴即可用,主要包含的功能有Excel模板下载、基于Excel数据导入、Excel数据导出。

根据实际情况修改一些细节即可,最后有结果展示,可以先看下结果,是否是您想要的。

台上一分钟,台下60秒,不喜勿喷。

觉得有用,麻烦点个赞和关注。

新建SpringBoot项目,引入下面的依赖

注:这个依赖已经整合了 poi 和poi-ooxm,无需单独引入。

如有对于POI和Excel有任何疑问,可移步1小时学会 POI 和 EasyExcel (超级详细)_涉世未深果子狸的博客-CSDN博客_easyexcel poi

                            com.alibaba            easyexcel            2.2.7        

数据导入导出执行原理和思路:

用户端逻辑:

1. 数据导入

        用户先下载模板,根据模板填入数据,然后点击上传;

2. 数据导出

        用户在界面选择需要导出的数据(导出条件),点击导出。

后台开发逻辑:

1. 模板下载

        利用easyExcel生成文件,然后将文件放进响应流中,同时设置响应头为文件下载,浏览器收到响应之后,回去解析流中的内容,然后进行下载。

2. 文件上传

        用在填写好Excel内容之后,会以文件上传的形式,将文件上传到服务端,此时,我们只需要利用EasyExcel将文件流中的数据读出来即可。

3. 数据导出

        后台在接收到用户的数据导出请求之后,会根据请求中的筛选条件,查询对应数据,再将对应的数据填充进对应的导出模板中,以流的形式响应给浏览器。其实和模板下载的差不错,只是模板下载没有数据,数据导出有数据而已。

 

代码实现

说明:以下代码,是我根据具体业务编写之后整理出来的,会有不足的地方,欢迎指教!

下拉框策略

如果没有此需求,可以不要此类。

import com.alibaba.excel.write.handler.SheetWriteHandler;import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;import org.apache.poi.ss.usermodel.*;import org.apache.poi.ss.util.CellRangeAddressList;import java.util.Map;import java.util.TreeMap;public class CustomSheetWriteHandler implements SheetWriteHandler {        private final Map map = new TreeMap<>();        private int index = 0;        private final int batchSize = 2000;    @Override    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {    }        @Override    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {        // excel下标从0开始,这里第二列的下拉选择内容        map.put(1, new String[]{"下拉内容一", "下拉内容二"});        // excel下标从0开始,这里第三列的下拉选择内容        map.put(3, new String[]{"北京市", "上海市", "重庆市", "天津市"});        DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();        map.forEach((k, v) -> {            // 创建sheet,突破下拉框255的限制            // 获取一个workbook            Workbook workbook = writeWorkbookHolder.getWorkbook();            // 定义sheet的名称            String sheetName = "sheet" + k;            // 1.创建一个隐藏的sheet 名称为 proviceSheet            Sheet proviceSheet = workbook.createSheet(sheetName);            // 从第二个工作簿开始隐藏            this.index++;            // 设置隐藏            workbook.setSheetHidden(this.index, true);            // 2.循环赋值(为了防止下拉框的行数与隐藏域的行数相对应,将隐藏域加到结束行之后)            for (int i = 0, length = v.length; i < length; i++) {                // i:表示你开始的行数 0表示你开始的列数                proviceSheet.createRow(i).createCell(0).setCellValue(v[i]);            }            Name category1Name = workbook.createName();            category1Name.setNameName(sheetName);            // 4 $A$1:$A$N代表 以A列1行开始获取N行下拉数据            category1Name.setRefersToFormula(sheetName + "!$A$1:$A$" + (v.length));            // 5 将刚才设置的sheet引用到你的下拉列表中,1表示从行的序号1开始(开始行,通常行的序号为0的行是表头),50表示行的序号50(结束行),表示从行的序号1到50,k表示开始列序号和结束列序号            CellRangeAddressList addressList = new CellRangeAddressList(1, batchSize, k, k);            DataValidationConstraint constraint8 = helper.createFormulaListConstraint(sheetName);            DataValidation dataValidation3 = helper.createValidation(constraint8, addressList);            // 阻止输入非下拉选项的值            dataValidation3.setErrorStyle(DataValidation.ErrorStyle.STOP);            dataValidation3.setShowErrorBox(true);            dataValidation3.setSuppressDropDownArrow(true);            dataValidation3.createErrorBox("提示", "此值与单元格定义格式不一致");            // validation.createPromptBox("填写说明:","填写内容只能为下拉数据集中的单位,其他单位将会导致无法入仓");            writeSheetHolder.getSheet().addValidationData(dataValidation3);        });    }}

 

批注策略

给表头添加批注,没有此需求可以不要

import com.alibaba.excel.write.handler.RowWriteHandler;import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;import com.alibaba.excel.write.metadata.holder.WriteTableHolder;import lombok.extern.slf4j.Slf4j;import org.apache.poi.ss.usermodel.Comment;import org.apache.poi.ss.usermodel.Drawing;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.xssf.usermodel.XSSFClientAnchor;import org.apache.poi.xssf.usermodel.XSSFRichTextString;@Slf4jpublic class CommentWriteHandler implements RowWriteHandler {    @Override    public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {    }    @Override    public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {    }    @Override    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {        Sheet sheet = writeSheetHolder.getSheet();        Drawing drawingPatriarch = sheet.createDrawingPatriarch();        // 在第一行 第二列创建一个批注        Comment comment1 =                drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)0, 0, (short)1, 1));        // 输入批注信息        comment1.setString(new XSSFRichTextString("批注1"));        // 将批注添加到单元格对象中        sheet.getRow(0).getCell(0).setCellComment(comment1);        Comment comment2 =                drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)1, 0, (short)2, 1));        // 输入批注信息        comment2.setString(new XSSFRichTextString("批注2"));        // 将批注添加到单元格对象中        sheet.getRow(0).getCell(1).setCellComment(comment2);        Comment comment3 =                drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)2, 0, (short)3, 1));        // 输入批注信息        comment3.setString(new XSSFRichTextString("批注3"));        // 将批注添加到单元格对象中        sheet.getRow(0).getCell(2).setCellComment(comment3);    }}

 

数据读取监听

导入数据时,程序解析和读取数据用,必须要!!!

import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import lombok.Getter;import lombok.NoArgsConstructor;import lombok.Setter;import java.util.ArrayList;import java.util.List;import java.util.Map;@Getter@Setter@NoArgsConstructorpublic class ExcelListener extends AnalysisEventListener {    // 加入一个判断标签,判断数据是否已经读取完    private volatile boolean retryLock = false;    // 解析完成后的数据集合, 监听对象初始化之后,立即初始化集合对象    private final List dataList = new ArrayList<>();    // 每次最多导入条数    private final int batchSize = 2000;        public List getDataList() {        while (true){            if (retryLock){                if (dataList.size() > batchSize){                    // 手动清空数据内存数据,减少内存消耗                    dataList.clear();                    throw new RuntimeException("一次最多导入"+ batchSize +"条数据");                } else {                    return dataList;                }            }        }    }        @Override    public void invoke(T data, AnalysisContext context) {        dataList.add(data);    }        @Override    public void invokeHeadMap(Map headMap, AnalysisContext context) {        //System.out.println("表头:" + headMap);    }        @Override    public void doAfterAllAnalysed(AnalysisContext context) {        // 数据解析完成,解锁        retryLock = true;    }        @Override    public void onException(Exception exception, AnalysisContext context){        throw new RuntimeException("Excel数据异常,请检查或联系管理员!");    }}

 

Excel工具类

封装统一的Excel操作入口

import com.alibaba.excel.EasyExcel;import com.alibaba.excel.ExcelWriter;import com.alibaba.excel.write.metadata.WriteSheet;import com.alibaba.excel.write.metadata.WriteTable;import com.alibaba.excel.write.metadata.style.WriteCellStyle;import com.alibaba.excel.write.metadata.style.WriteFont;import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.apache.poi.ss.usermodel.HorizontalAlignment;import org.apache.poi.ss.usermodel.IndexedColors;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;import java.util.List;@Slf4jpublic class ExcelUtil {        public static void export(String filename, List dataResult, Class clazz, HttpServletResponse response) {        response.setStatus(200);        OutputStream outputStream = null;        ExcelWriter excelWriter = null;        try {            if (StringUtils.isBlank(filename)) {                throw new RuntimeException("'filename' 不能为空");            }            String fileName = filename.concat(".xlsx");            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));            outputStream = response.getOutputStream();            // 根据不同的策略生成不同的ExcelWriter对象            if (dataResult == null){                excelWriter = getTemplateExcelWriter(outputStream);            } else {                excelWriter = getExportExcelWriter(outputStream);            }            WriteTable writeTable = EasyExcel.writerTable(0).head(clazz).needHead(true).build();            WriteSheet writeSheet = EasyExcel.writerSheet(fileName).build();            // 写出数据            excelWriter.write(dataResult, writeSheet, writeTable);        } catch (Exception e) {            log.error("导出excel数据异常:", e);            throw new RuntimeException(e);        } finally {            if (excelWriter != null) {                excelWriter.finish();            }            if (outputStream != null) {                try {                    outputStream.flush();                    outputStream.close();                } catch (IOException e) {                    log.error("导出数据关闭流异常", e);                }            }        }    }        private static ExcelWriter getTemplateExcelWriter(OutputStream outputStream){        return EasyExcel.write(outputStream)                .registerWriteHandler(new CommentWriteHandler())        //增加批注策略                .registerWriteHandler(new CustomSheetWriteHandler())    //增加下拉框策略                .registerWriteHandler(getStyleStrategy())               //字体居中策略                .build();    }        private static ExcelWriter getExportExcelWriter(OutputStream outputStream){        return EasyExcel.write(outputStream)                .registerWriteHandler(getStyleStrategy())   //字体居中策略                .build();    }        private static HorizontalCellStyleStrategy getStyleStrategy(){        WriteCellStyle headWriteCellStyle = new WriteCellStyle();        //设置背景颜色        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());        //设置头字体        WriteFont headWriteFont = new WriteFont();        headWriteFont.setFontHeightInPoints((short)13);        headWriteFont.setBold(true);        headWriteCellStyle.setWriteFont(headWriteFont);        //设置头居中        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);        // 内容策略        WriteCellStyle writeCellStyle = new WriteCellStyle();        // 设置内容水平居中        writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);        return new HorizontalCellStyleStrategy(headWriteCellStyle, writeCellStyle);    }        public static List importExcel(MultipartFile file, Class clazz){        if (file == null || file.isEmpty()){            throw new RuntimeException("没有文件或者文件内容为空!");        }        List dataList = null;        BufferedInputStream ipt = null;        try {            InputStream is = file.getInputStream();            // 用缓冲流对数据流进行包装            ipt = new BufferedInputStream(is);            // 数据解析监听器            ExcelListener listener = new ExcelListener<>();            // 读取数据            EasyExcel.read(ipt, clazz,listener).sheet().doRead();            // 获取去读完成之后的数据            dataList = listener.getDataList();        } catch (Exception e){            log.error(String.valueOf(e));            throw new RuntimeException("数据导入失败!" + e);        }        return dataList;    }} 

 

创建导入数据模板类

可以理解为这个类是我们和客户之间的约定,程序根据这个模板类生成对应的Excel文件,客户根据Excel文件将数据填充进来。然后用户将填充好的Excel文件上传到我们的程序中,我们还得根据这个模板类来解析读取用户填充的数据。

根据实际业务调整,上面的工具类会根据提供的模板生成对应的Excel文件。

import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.write.style.ColumnWidth;import lombok.Data;import lombok.experimental.Accessors;import javax.validation.constraints.NotEmpty;import java.io.Serializable;@Datapublic class ImportExcelVo implements Serializable {    private static final long serialVersionUID = 1L;    @ColumnWidth(20)    @ExcelProperty(value = "公司名称", index = 0)    private String name;    @ColumnWidth(20)    @ExcelProperty(value = "公司联系电话", index = 1)    private String phone;    @ColumnWidth(28)    @ExcelProperty(value = "公司统一社会信用代码", index = 2)    private String creditCode;    @ColumnWidth(15)    @ExcelProperty(value = "区域", index = 3)    private String province;    @ColumnWidth(15)    @ExcelProperty(value = "公司法人", index = 4)    private String legalPerson;    @ExcelProperty(value = "备注", index = 5)    private String remark;}

 

创建数据导出模板

根据此模板,向用户展示用户可以看到的字段。

根据实际业务调整,上面的工具类会根据提供的模板生成对应的Excel文件。

import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.write.style.ColumnWidth;import lombok.Data;import lombok.experimental.Accessors;import java.io.Serializable;@Data   // Lombok注解,用于生成getter setter@Accessors(chain = true) //Lombok注解,链式赋值使用public class ExportExcelVo implements Serializable {    private static final long serialVersionUID = 1L;    @ColumnWidth(25)    @ExcelProperty(value = "企业名称", index = 0)    private String name;    @ColumnWidth(25)    @ExcelProperty(value = "社会统一信用代码", index = 1)    private String creditCode;    @ColumnWidth(15)    @ExcelProperty(value = "曾用名", index = 2)    private String formerName;    @ColumnWidth(15)    @ExcelProperty(value = "公司法人", index = 3)    private String legalPerson;    @ExcelProperty(value = "区域", index = 4)    private String province;    @ExcelProperty(value = "录入时间", index = 5)    private String createTime;    @ColumnWidth(15)    @ExcelProperty(value = "公司股东", index = 6)    private String stockholder;    @ExcelProperty(value = "企业联系方式", index = 7)    private String contact;}

 

Web接口

import lombok.extern.slf4j.Slf4j;import com.xxx.xxx.domain.vo.ExportExcelVo;import com.xxx.xxx.domain.vo.ImportExcelVo;import com.xxx.xxx.util.CommonResponse;import com.xxx.xxx.util.ExcelUtil;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;@Slf4j@RestController@RequestMapping("/api/excel")public class ExcelController {        @RequestMapping(value = "/template", method = RequestMethod.GET)    public CommonResponse template(HttpServletResponse response){        String fileName = "导入模板下载" + System.currentTimeMillis();        try {            ExcelUtil.export(fileName, null, ImportExcelVo.class, response);        } catch (Exception e) {            return CommonResponse.error("模板下载失败" + e.getMessage());        }        return CommonResponse.success("模板下载成功!");    }        @RequestMapping(value = "/import", method = RequestMethod.POST)    public CommonResponse importEvents(MultipartFile file){        try {            List list = ExcelUtil.importExcel(file, ImportExcelVo.class);            System.out.println(list);            return CommonResponse.success("数据导入完成");        } catch (Exception e) {            return CommonResponse.error("数据导入失败!" + e.getMessage());        }    }        @RequestMapping(value = "/export", method = RequestMethod.GET)    public CommonResponse export(Long size, HttpServletResponse response){        // 模拟根据条件在数据库查询数据        ArrayList excelVos = new ArrayList<>();        for (int i = 1; i <= size; i++) {            ExportExcelVo excelVo = new ExportExcelVo();            excelVo.setContact(String.valueOf(10000000000L + i));            excelVo.setName("公司名称" + i);            excelVo.setCreditCode("社会性用代码" + i);            excelVo.setProvince("地区" + i);            excelVo.setLegalPerson("法人" + i);            excelVo.setFormerName("曾用名" + i);            excelVo.setStockholder("投资人" + i);            excelVo.setCreateTime(new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(new Date()));            excelVos.add(excelVo);        }        String fileName = "数据导出" + System.currentTimeMillis();        try {            ExcelUtil.export(fileName, excelVos, ExportExcelVo.class, response);        } catch (Exception e) {            return CommonResponse.error("数据导出成功" + e.getMessage());        }        return CommonResponse.success("数据导出失败!");    }}

至此整个Excel导入导出代码完毕!

 

结果展示

模板下载

  1. 浏览器访问模板下载接口,然后会根据接口返回的内容进行解析

 

  1. Excel文件查看

 

数据导入

  1. 填充数据,在下载下来的模板中填入数据
  1. 利用PostMan进行文件上传
  1. 控制台输出

 

数据导出

  1. 浏览器访问数据导出接口
  1. 内容展示

 

 

转载请注明:文章转载自 http://www.konglu.com/
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【基于EasyExcel的数据导入导出(复制可用)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2